I tried to save data to the CloudKit programmatically with success but I got an error when I fetch data from CloudKit
I got an error
> <CKError 0x608000052060: "Invalid Arguments" (12/2015); server message
> = "Field '___recordID' is not marked queryable"; uuid = 19F1E556-5384-42FD-8F65-9FD8A9C9523D; container ID =
> "iCloud.com.mywebsite.CloudDemo">
This is my code.
func saveNewRecordTypeToCloud() {
// Prepare the record to save
var record = CKRecord(recordType: "Members")
record.setValue("test", forKey: "name")
record.setValue("test", forKey: "surname")
// Get iCloud Database
let cloudContainer = CKContainer.defaultContainer()
let database = CKContainer.defaultContainer().privateCloudDatabase
// Save the record to iCloud
database.saveRecord(record, completionHandler: { (record:CKRecord!, error:NSError! ) in
if error != nil {
NSLog(error.localizedDescription)
} else {
dispatch_async(dispatch_get_main_queue()) {
println("finished")
}
}
})
}
func getRecordsFromCloud() {
// Fetch data using Convenience API
let cloudContainer = CKContainer.defaultContainer()
let publicDatabase = CKContainer.defaultContainer().privateCloudDatabase
let predicate = NSPredicate(value: true)
let sort = NSSortDescriptor(key: "creationDate", ascending: false)
let query = CKQuery(recordType: "Members", predicate: predicate)
query.sortDescriptors = [sort]
publicDatabase.performQuery(query, inZoneWithID: nil, completionHandler: {
results, error in
if error == nil {
self.members = results as! [CKRecord]
println(self.members)
} else {
println(error)
}
}) }
To resolve such the problem, I had to set the Metadatas Index via Web DashBoard but I want to know if I could set the Metadatas Index by the code?
If so, please give me some code sample.
Thank you for all answers.
Sorry, there is no way to set indexes from code. You have to do this in the CloudKit dashboard.
Related
I'm currently developing an application in swift 3 for a school project that requires uploading files to google drive .
The upload is currently working , but i need to inform users with an upload bar.
Here the current code
let folderId: String = folders[indexPath.row].folderId
let metadata = GTLRDrive_File.init()
metadata.name = "Ruin.mp3"
// metadata.mimeType = "application/vnd.google-apps.photo"
metadata.parents = [folderId]
guard let filePath = Bundle.main.path(forResource: "Ruin", ofType: "mp3") else {
return
}
guard let fileData = FileManager.default.contents(atPath: filePath) else {
return
}
let uploadParameters = GTLRUploadParameters(data: fileData , mimeType: "audio/mpeg")
uploadParameters.shouldUploadWithSingleRequest = true
let query = GTLRDriveQuery_FilesCreate.query(withObject: metadata, uploadParameters: uploadParameters)
query.fields = "id"
self.service.executeQuery(query, completionHandler: {(ticket:GTLRServiceTicket, object:Any?, error:Error?) in
if error == nil {
// print("File ID \(files.identifier)")
}
else {
print("An error occurred: \(error)")
}
})
Thanx in advance
I have some trouble with the code below.
Though it works, there is some timing problem.
First let me say what I expect, I suppose the completion handler should be run when the data download is complete and my image ready to use. But reality seems to be quite different. When I try it the completion handler is called right away (I can see 'All OK' in the console) as if everything was instantaneous. But the image gets actually displayed much later. What am I missing?
let imageURL = URL(string: myURLString)
session = URLSession.shared,
_ = session.dataTask(with: imageURL) {[weak self]
(data: Data?, response: URLResponse?, error: Error?) in
if error == nil {
print("All OK")
self?.theImage = UIImage(data: data!)
self?.theView.image = self?.theImage
} else {print(error!)}
DispatchQueue.main.async {
self?.activityIndicator.stopAnimating()
self?.theView.setNeedsDisplay()
}
}.resume()
Can you try this code?
The control should not be actually going inside the handler at first call. And I think there are a few mistakes in your code as well which I pointed out earlier, especially the main thread is required for updating UI.
let session : URLSession
let config = URLSessionConfiguration.default
var resultFromServer: Any?
let responseResultData = [String:Any]()
session = URLSession(configuration: config, delegate: nil, delegateQueue: nil)
session.dataTask(with: request) { (data, response, error ) in
if error != nil {
DispatchQueue.main.async(execute: {
session.invalidateAndCancel()
})
}else{
let httpResponse: HTTPURLResponse = response as! HTTPURLResponse
do{
resultFromServer = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)
if httpResponse.statusCode == 200 || httpResponse.statusCode == 201 || httpResponse.statusCode == 202 || httpResponse.statusCode == 204 || httpResponse.statusCode == 203 {
if let respArr = resultFromServer as? [Any]{
//resp is array
}else if let respdict = resultFromServer as? [String : Any] {
//resp is dict
}else{
//resp is something else maybe string, etc
}
}
else {
//error status code something like 500, 404, etc
}
}
catch let error as NSError {
DispatchQueue.main.async(execute: {
session.invalidateAndCancel()
})
}
}
session.finishTasksAndInvalidate()
}.resume()
let todoEndpoint: String ="http://localhost:16789/api/product"
guard let url = NSURL(string: todoEndpoint) else {
print("Error: cannot create URL")
return
}
let urlRequest = NSURLRequest(url: url as URL)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) in
guard let responseData = data else {
print("Error: did not receive data")
return
}
guard error == nil else {
print("error calling GET")
print(error)
return
}
do{
self.users = try JSONSerialization.jsonObject(with: responseData, options: []) as? Array}
catch{
print("Error parsing")
}
}
task.resume()
this is my Output my API
[{"ProductId":2,"Category":"Laptop","Brand":"Apple","ModelName":"MacBook Pro","SerialNumber":"Test1","DatePurchased":"2016-08-12T00:00:00","EmployeeName":"Vismita Shetty","DateAssigned":"2017-01-17T00:00:00"},{"ProductId":4,"Category":"Keyboard","Brand":"Logitech","ModelName":"K200","SerialNumber":"TestKeyboard1","DatePurchased":"2017-01-23T03:02:13.247","EmployeeName":"Vismita Shetty","DateAssigned":"2017-01-17T00:00:00"},{"ProductId":5,"Category":"Keyboard","Brand":"Logitech","ModelName":"K200","SerialNumber":"testkeyboard2","DatePurchased":"2017-01-23T03:03:26.07","EmployeeName":"Suraj Pangam","DateAssigned":"2017-01-17T00:00:00"}]
What I currently trying to do convert user into different variable which will be of type Array of dictionaries in swift. So that Each object can be accessed by key. I want to make it generic so that even some properties got changed it won't matter as it won't be accessed by providing property name. Like (users[indexPath.row] as? [String: AnyObject])?["EmployeeName"] as! String!.
Instead if i make it to dictionary i will be easily do it by running for (key,value) loop for array of dictionary.
I am following tutorial, as it is pretty old tutorial and they actually used GoogleMaps framework package instead of pods which I followed and everything was going smooth till I reached Spotting a Custom Location. In that section they asked to update func geocodeAddress as below, and add var mapTasks = MapTasks() in ViewController.swift file which I did but it gives me error.
Use of unresolved identifier 'MapTasks'
error
func geocodeAddress(address: String!, withCompletionHandler completionHandler: ((status: String, success: Bool) -> Void)) {
if let lookupAddress = address {
var geocodeURLString = baseURLGeocode + "address=" + lookupAddress
geocodeURLString = geocodeURLString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
let geocodeURL = NSURL(string: geocodeURLString)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
let geocodingResultsData = NSData(contentsOfURL: geocodeURL!)
var error: NSError?
let dictionary: Dictionary<NSObject, AnyObject> = NSJSONSerialization.JSONObjectWithData(geocodingResultsData!, options: NSJSONReadingOptions.MutableContainers, error: &error) as Dictionary<NSObject, AnyObject>
if (error != nil) {
println(error)
completionHandler(status: "", success: false)
}
else {
// Get the response status.
let status = dictionary["status"] as String
if status == "OK" {
let allResults = dictionary["results"] as Array<Dictionary<NSObject, AnyObject>>
self.lookupAddressResults = allResults[0]
// Keep the most important values.
self.fetchedFormattedAddress = self.lookupAddressResults["formatted_address"] as String
let geometry = self.lookupAddressResults["geometry"] as Dictionary<NSObject, AnyObject>
self.fetchedAddressLongitude = ((geometry["location"] as Dictionary<NSObject, AnyObject>)["lng"] as NSNumber).doubleValue
self.fetchedAddressLatitude = ((geometry["location"] as Dictionary<NSObject, AnyObject>)["lat"] as NSNumber).doubleValue
completionHandler(status: status, success: true)
}
else {
completionHandler(status: status, success: false)
}
}
})
}
else {
completionHandler(status: "No valid address.", success: false)
}
}
Here is my GitHub repository
Thank you in advance.
If you fully read that tutorial, you will find in the instruction that you need to create a file name MapTasks which is a class.
You can just copy this file from GitHub and add it to your project.
I have the following code snippet to load an image from an url:
let url = NSURL(string: imageUrl)
let data = NSData(contentsOfURL: url!)
let image = UIImage(data: data!)
In case that my variable imageUrl has a valid string value, what is the most secure way to protect this code against possible edge cases?
Following code seems not to be very handy:
if let url = NSURL(string: imageUrl) {
if let data = NSData(contentsOfURL: url) {
if let image = UIImage(data: data) {
// success -> do something with the image...
}
else {
// print error message
}
}
else {
// print error message
}
}
else {
// print error message
}
The best practice is not to use a synchronous method like contentsOfURL to load data from over the network.
The recommended way is NSURLSession which works asynchronously.
This is a simple example with a completion block and an enum with associated types,
it catches all possible errors
enum Result {
case Success(UIImage), Failure(NSString)
}
func loadImage(string : String, completion: (Result) -> ()) {
guard let url = NSURL(string: string) else {
completion(.Failure("Bad URL"))
return
}
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
completion(.Failure(error!.localizedDescription))
} else {
guard let image = UIImage(data: data!) else {
completion(.Failure("Could not load image data"))
return
}
completion(.Success(image))
}
}.resume()
}
Call it with:
loadImage("http://myserver.com/path/to/image.png") { result in
switch result {
case .Success(let image) :
// do something with the image
case .Failure(let error) :
print(error)
}
}