CKRecord fetch return 1 record with empty RecordID - ios

Record from iCloud container is fetched, but there is no RecordID. At the same time in the panel on the site, I see it. I tried to extract the record from another application, I registered the necessary container in the settings - and it was extracted without error.
I do not understand - this is a bug Xcode? After all, the extraction code is identical in the second application, where everything works. And in the debugger at the bottom left you can see that RecordID is not empty.
Code:
privateDatabase.perform(query, inZoneWith: nil) { (results, error) -> Void in
if error != nil {
print(error!.localizedDescription)
result(false)
} else if results != nil, results!.count > 0, let me = results?[0] {
let RN = (me[.recordID] as! CKRecord.ID).recordName
Error:
Thread 2: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Variables View Console:
_recordName __NSCFString * #"UA-kuka-2018-11-16 11:27:59" 0x00000001c0644320

The proper way to get the recordID of a CKRecord is to use the recordID property.
Assuming me is actually a CKRecord:
let RN = me.recordID.recordName

Related

CloudKit Error Differentiation

I need some help to learn how to properly handle errors when fetching records via CloudKit. Currently I have an app that saves numerous records in the cloud, and will load them at launch. I have been referencing the records using a CKReference, and anytime I save the reference I use the CKReferenceAction.DeleteSelf option. A problem I've encountered periodically is that when a referenced record is deleted, sometimes there can be a significant amount of time before the reference deletes itself. This has caused me to occasionally come across the situation where my app has fetched a CKReference for a record that no longer exists. I'm able to manually find out when this happens just by inserting print(error!) in my error handler. What I would like to know is how I can add some code to detect this specific error i.e. if error.localizedDescription == ??? {.
Here is the basic code I'm using for the fetch:
let fetch = CKFetchRecordsOperation(recordIDs: recordIDs)
fetch.perRecordCompletionBlock = { (record:CKRecord?, recordID:CKRecordID?, error: NSError?) in
if error != nil {
// Error Line A (See below)
print("ERROR! : \(error!.localizedDescription)")
// Error Line B (See below)
print("ERROR: \(error!)")
}
else if let record = record {
// Record was found
}
}
if let database = self.privateDatabase {
fetch.database = database
fetch.start()
}
And then when it tries to fetch the non-existent record, here is the error message that prints out in the compiler window:
a) ERROR! : Error fetching record <CKRecordID: 0x10025b290; dbbda7c3-adcc-4271-848f-6702160ea34f:(_defaultZone:__defaultOwner__)> from server: Record not found
b) ERROR: <CKError 0x125e82820: "Unknown Item" (11/2003); server message = "Record not found"; uuid = (removed); container ID = "(removed)">
Above in error line B, where it says CKError 0x125e82820:, can I use this to create an if statement to check for this specific error type? I really could use any help finding a way to resolve this issue properly when it happens. I have set up some loading structure for my app, and when it thinks there is a record it needs to find, but can't, it screws up my loading process. I would really appreciate any help I can get, I assume it's an easy solution, but apparently not one I've been able to find. Thank you!
UPDATE -
Thanks to #AaronBrager, I was able to find the correct solution. You can verify the error code to match it to any specific error, and the domain to make sure it's a CKError. Here is the solution that works for me:
let fetch = CKFetchRecordsOperation(recordIDs: recordIDs)
fetch.perRecordCompletionBlock = { (record:CKRecord?, recordID:CKRecordID?, error: NSError?) in
if error != nil {
if error!.code == CKErrorCode.UnknownItem.rawValue && error!.domain == CKErrorDomain {
// This works great!
}
}
else if let record = record {
// Record was found
}
}
if let database = self.publicDatabase {
fetch.database = database
fetch.start()
}
You should be able to uniquely identify an error's cause by inspecting its domain and code variables. Same domain and code, same problem. And unlike localizedDescription, it won't change between users.

Parse query on array of pointers only retrieving first object

In the code below, self.arrayOfLikers is an array of Pointers to Parse User Objects. Which looks like this on Parse:
var query = PFQuery(className: "Item")
query.includeKey("likedBy")
query.getObjectInBackgroundWithId(theObjectIdOfTheItem!) { (returnedItem, error) in
if error != nil {
print(error)
}
else {
returnedItem?.fetchInBackgroundWithBlock({ (fetchedReturnedItem, error) in
if error != nil {
print(error)
}
else {
dispatch_async(dispatch_get_main_queue(),{
self.arrayOfLikers = fetchedReturnedItem!["likedBy"] as! [PFUser]
print("about to print the arrayOfLikers")
print(self.arrayOfLikers)
self.tableView.reloadData()
})
}
})
}
}
When I print my self.arrayOfLikers I can see that the first index contains a correctly retrieved PFUser object. Below is a print statement from Xcode:
In another viewController, I am storing these pointers when the user taps the "like" button. This is how I am storing those pointers:
Creation of the userPointer:
let userPointer = PFObject(outDataWithClassName: "User", objectId: user?.objectId)
(oddly, the Parse docs use withoutDataWithClassName, but when I put this in, Xcode keeps making me change it outDataWithClassName, and it compiles, so I guess this is correct?)
Storing the userPointer: (please note, theItemObject is an object set by a previous VC):
theItemObject!.addObject(userPointer, forKey: "likedBy")
Consequently, Parse via Xcode gives me this error:
2016-03-30 23:38:47.749 Trashly[5482:1512409] [Error]: object not found for get (Code: 101, Version: 1.12.0)
Optional(Error Domain=Parse Code=101 "object not found for get" UserInfo={code=101, temporary=0, error=object not found for get, NSLocalizedDescription=object not found for get})
Any ideas why my query is not getting any user objects but the first one?

NSInvalidArgumentException when trying to retrieve images

I am getting an error using a "properly working" code in another place:
[Error]: Caught "NSInvalidArgumentException" with reason "*** -[_NSPlaceholderData
initWithContentsOfFile:options:error:]: nil file argument"
I declared an array of arrays group:[[AnyObject]]
In my CellForRowAtIndexPath method in my UITableView I am starting the following query based on an array which is an element of group => group[indexPath.row].
I can get the necessary data without a problem, but when I try to use my getDataInBackgroundWithBlock() method, it throws the error above.
var memberPhotoImages:[UIImage] = [UIImage]()
let buttonImageQuery = PFUser.query()
buttonImageQuery?.whereKey("objectId", containedIn: group[indexPath.row])
buttonImageQuery?.findObjectsInBackgroundWithBlock({ (results, error) -> Void in
if error != nil {
print(error)
} else {
self.memberPhotosFiles.removeAll()
if let results = results {
for result in results {
let buttonPicture = result["firstImage"] as! PFFile
self.memberPhotosFiles.append(buttonPicture)
buttonPicture.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error != nil {
//...
} else {
if let data = imageData {
print("success!")
}}}}}}})
return cell
}
Any ideas how to solve this? tried a lot of typecasting so far, but it must be something else.
edit: It prints "Success!", but also the error msg.
I had to guess from the error, it looks like you're trying to access a file that doesn't exist on the device -[_NSPlaceholderData initWithContentsOfFile:options:error:]: nil file argument The issue could be that you're accessing something from a place where the simulator can get to it (possibly inside the iOS Simulator's files, which are in Application Support,) but the device cannot. Check your code for any hard-coded paths that might lead to a place on your computer rather than accessing the device's filesystem.
It show that your file argument is nil. Most of such cases are due to different file path between simulator and device. Check your code about loading file and compare the path between simulator and device.

Why does the "objects: [PFObject]?" parameter of Parse's findObjectsInBackgroundWithBlock function return nil?

This is for an existing class on Parse called "HellsKitchen" and I have tried others, but always receive nil on objects.
let query = PFQuery(className: "HellsKitchen")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
print("got em: \(objects)")
} else {
print("error: \(error!.userInfo)")
}
}
All of the other posts about this refer to the block closure when they had objects as [AnyObject]? but it has since changed sometime in late 2015 and I no longer need to cast it as PFObject as all the answers say.
I have tried adding App Transport Security Settings > Allow Arbitrary Loads = YES to my Info.plist to no avail.
I get no error from the block either. It passes into the if statement because error == nil and prints "got em: nil".
How can I get my objects?

PFQuery found a nonexistent object - Swift

I'm trying to query a nonexistent object like this code bellow, but always "Mike" is found. What could be wrong? Everything is working great (Save, Delete, Update and Query without error recognition).
var query = PFQuery(className:"Restaurant")
query.whereKey("clientname", equalTo:"Mike")
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if (error == nil) {
print ("Found")
}
else {
print ("Not Found")
}
}
Try checking (debugging) what "objects" actually is. I think you will see that it is an empty array, meaning it did NOT find Mike.
An empty array of results is not a query error. The query succeeds, but finds no objects. So not getting an error does not mean "Found". It just means there was no error.

Resources