CloudKit CKSubscription, subscriptionID - ios

I am trying to study CloudKit and I saw this. https://github.com/ghvillasboas/CloudKitTest
After I have followed that instruction, I can run app and save, fetch data.
However, I saw this code
CKSubscription *subscription = [[CKSubscription alloc]
initWithRecordType:GVCloudKitRecordType predicate:[NSPredicate predicateWithFormat:#"TRUEPREDICATE"] subscriptionID:GVCloudKitSubscriptionId options:CKSubscriptionOptionsFiresOnRecordCreation];
GVCloudKitSubscriptionId = br.com.cocoaheads.cloudkittest.newHeroSubscription for that one. But, for me, how can I create subscriptionID? May I know from where I can register that or get that?

You can define your own subscriptionID. Just remember that ID so that you can also unregister. Create a logical ID. Something like "all" if you are using a true predicate.

Related

Get user_pseudo_id from Firebase iOS SDK

In Firebase Analytics, there is a user property called user_pseudo_id, which is automatically set by Firebase, and it seems to fit our needs.
The doc says:
The pseudonymous id (e.g., app instance ID) for the user.
but when I get Instance ID using InstanceID.instanceID().instanceID(handler:) it give different value from what we see in Big Query.
Any thoughts on how to get it? Thanks!
You should be using the appInstanceID method of FIRAnalytics class.
NSString *instanceID = [FIRAnalytics appInstanceID];
NSLog(#"INSTANCE ID: %#", instanceID);
Using Swift 5 you can get this as follows.
let instanceID = Analytics.appInstanceID()
print(instanceID)

cloudkit notifications for a specific field within a record

I have cloudkit notifications working. When someone changes the record, the subscribers are notified. My subscription definition looks like:
NSPredicate *searchConditions = [NSPredicate predicateWithFormat:#"%K = %#", CLOUDKIT_PUBLIC_ID_GUID, theCloudGUID];
int subscriptionOptions = CKSubscriptionOptionsFiresOnRecordUpdate | CKSubscriptionOptionsFiresOnRecordDeletion;
CKSubscription *publicSubscription = [[CKSubscription alloc] initWithRecordType:CLOUDKIT_RECORDNAME_PUBLIC_ID
predicate:searchConditions
options:subscriptionOptions];
CKNotificationInfo *notificationInfo = [CKNotificationInfo new];
notificationInfo.alertLocalizationKey = CLOUDKIT_NOTIFICATION_PUBLIC;
notificationInfo.shouldBadge = NO;
notificationInfo.alertBody = CLOUDKIT_NOTIFICATIONBODY_PUBLIC;
publicSubscription.notificationInfo = notificationInfo;
[publicDatabase saveSubscription:publicSubscription completionHandler:^(CKSubscription * _Nullable subscription, NSError * _Nullable error)
{
//error handling
}
The thing is, there are multiple fields in this record. I only want to alert the subscriber when one specific field changes.
When creating the subscription, is there a way to set the search predicate to detect a change in a specific field? I read through the various Predicate docs, but didn't see this specifically mentioned.
Or, when receiving the notification, is there a way to see which fields changed? In didReceiveRemoteNotification I tried:
CKQueryNotification *queryNotification = [CKQueryNotification notificationFromRemoteNotificationDictionary:userInfo];
But queryNotification.recordFields is null.
As a worst case, I have considered breaking the specific field out into it's own record, but then I have the overhead of maintaining more records tied together by a common GUID. I was hoping to keep this more compact.
Your question is aging a bit, so maybe you already figured this out, but using the desiredKeys property may help: https://developer.apple.com/documentation/cloudkit/cknotificationinfo/1514931-desiredkeys
If these notifications are silent pushes, you could look at the payload to see if certain keys changed and have your app react accordingly.
If these are push (visible-to-the-user) notifications, I don't think you can push based on the key changing per se. You could set an NSPredicate on your CKQuerySubscription if you were testing how the value changed (is it equal to this or not equal to that, etc.), but I'm not sure about it being triggered for any change at all.

How to send multiple columns of information using CKSubscription

I can get CKSubscription work using CKNotificationInfo() and CKNotificationInfo.alertBody. So I can send one piece of information. I'm trying to make CKSubscription send the user something like message, username, location, etc in a dictionary format. I've dabbled with CKNotificationInfo.alertLocaliztionKey and CKNotificationInfo.alertLocaliztionArgs but just can't seem to make it work. It feels like i'm missing something small because CKSubscription shouldn't be this troublesome to make it work.
Because that is not what is intended in the notification framework. What you do get back is information about WHAT has changed, and then you have to fetch this data and do what ever you want to do. I have made an app which both tells the user that something has changed and silently in the back refreshes the local data:
let cloudKitNotifiction = CKQueryNotification(fromRemoteNotificationDictionary: uif)
if cloudKitNotifiction.notificationType == CKNotificationType.Query{
if let recordId = cloudKitNotifiction.recordID{
let ccs = CloudCoreSynchronizer()
ccs.syncOneCustomerFromCloudToCore(recordId)
resetBadgeCounter()
}
}
To make this work you have to enable push notifications and background modes, if you want it to happen when the app is in the background.Hope this helps. PS: Just disregard the inapp purchase thing, it has nothing to do with this

CKSubscription to creatorUserRecordID never arrives

I create CKSubscription using the following code:
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:#"(creatorUserRecordID == %#)", self.myRecordId];
CKSubscription *subscription2 = [[CKSubscription alloc]
initWithRecordType:#"Message"
predicate:predicate2
options:CKSubscriptionOptionsFiresOnRecordCreation];
where self.myRecordId is CKRecordID of the current logged user. I do this because I would like to receive notification when I create a new object (of type Message) but the problem is that notification never arrives. Anyone has idea why?
You should complete the missing steps described in the Quick Start Guide namely set the notification object, assign it to the subscription, and assign the subscription to the public database:
Please note the verification steps on the original source.

CloudKit subscription with "CONTAINS" predicate

I am trying to setup a CloudKit subscription based on testing membership in an array.
The code I'm using to create the subscription is as follows:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"users CONTAINS %#", userID];
CKSubscription *itemSubscription = [[CKSubscription alloc] initWithRecordType:#"foo"
predicate:predicate
options:CKSubscriptionOptionsFiresOnRecordCreation|CKSubscriptionOptionsFiresOnRecordUpdate];
CKNotificationInfo *notificationInfo = [[CKNotificationInfo alloc] init];
[notificationInfo setAlertLocalizationKey:#"Record notification"];
[notificationInfo setShouldBadge:YES];
[itemSubscription setNotificationInfo:notificationInfo];
[database saveSubscription:itemSubscription completionHandler:^(CKSubscription *subscription, NSError *error) {
NSLog(#"Error: %#, Subscription: %#", error, subscription);
}];
The log shows that the subscription is created successfully, however when I test by adding or changing a record via the CloudKit admin console I never get a notification on device.
I am able to receive notifications for subscriptions with other kinds of predicates (I've tested with a simple true predicate, and one that tests equality against a string field), so I know I have the notification code setup correctly.
I've also verified that my predicate listed above works when used in a fetch records query, so I know the predicate is setup correctly for the record type I have in CloudKit.
Has anyone been able to get subscription notifications with a predicate that tests for membership in an array?
After playing around, I found that unless I set notificationInfo.alertbody the subscription never fired.
So try setting it to "Test" first, then after set it to "". I found it continued to work after I set it to a blank string (though I didn't try setting it blank to start with), and as a blank string it doesn't show a notification, but my handler still gets called, which was what I was after.
With iOS 8.1.1 / Xcode 6.1.1

Resources