2

I need a way to connect a CKQueryNotification to a CKRecord or CKSubscription so I can receive updates/inserts/deletes on multiple record types. I'm successfully receiving CKNotifications and this is the payload:

{
    ck =     {
        ce = 2;
        cid = "<my cloud container id>";
        nid = "<unknown guid>";
        qry =         {
            dbs = 2;
            fo = 1;
            rid = "<the record id>";
            sid = "<THIS IS THE SUBSCRIPTION ID>";
            zid = "_defaultZone";
            zoid = "_defaultOwner";
        };
    };
}

I can get the subscription ID by the notification payload, and I could tie the subscription ID to a local cache that knows the record type, but I want to use a CKFetchNotificationChangesOperation to retrieve unread notifications, and at that point I only have a CKQueryNotification object.

The CKQueryNotification object only has a CKRecordID, and as far as I can tell, I can't get a CKRecord from the CKRecordID. I could perform a query on all of my CKRecord->recordType's in my container but that doesn't seem right.

Any help is appreciated!

Matt W.
  • 956
  • 9
  • 21

1 Answers1

6

if you receive a push notification, then you should see if you can cast it to a CKQueryNotification. Indeed you should call -[CKDatabase fetchRecordWithID:completionHandler:] for getting the complete record. you can then use the .recordType to see what kind of record it is.

You only have a problem when you have multiple subscriptions for the same recordType. You could solve that by checking if the object complies to the predicate that you used for that subscription. See the predicate.evaluateWithObject method for this. You can not use this if you have a predicate for a CKReference.

If you want a working sample of this, then you could have a look at: https://github.com/evermeer/EVCloudKitDao Which has some other nice features like automatic parsing from and to CKRecord and caching on device of results.

Matt W.
  • 956
  • 9
  • 21
Edwin Vermeer
  • 13,017
  • 2
  • 34
  • 58
  • Awesome thanks! it was the fetchRecordWithID that I was missing. – Matt W. Feb 04 '15 at 16:33
  • 1
    Hey Edwin, the fetchRecordWithId: doesn't work with deletes. I'm getting a "Record not found." Which makes sense since it's been deleted. How do I find the recordType for deleted objects? – Matt W. Feb 05 '15 at 08:21
  • Ah, true.. For deletes you have to search your cache for that particular recordId and then remove it from cache. For updates you should do something similar. checking the predicate is only necessary for new records. – Edwin Vermeer Feb 05 '15 at 08:27
  • 2
    Dang. I was trying to avoid searching my cache for the recordID. Thanks so much for the help! – Matt W. Feb 05 '15 at 08:30
  • 1
    The easiest way to do that is by using https://github.com/pNre/ExSwift and then execute a remove method with comparison on your data collection. – Edwin Vermeer Feb 05 '15 at 08:34
  • 1
    Thanks for the tips. Those swift extensions will come in handy! I'm using Core Data for the current project for the NSEntityDescription description of objects and the child context functionality. So far it is working well for my local cache, but it may be doing things the hard way. – Matt W. Feb 05 '15 at 08:43
  • Hi, I am wondering if fetchRecordWithID will hit the request limit (40/sec) if I have more than 40 users subscribe to the event. – Frank Sep 10 '16 at 22:01