Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CloudKit Push Notifications didReceiveRemoteNotification never called

I am using CloudKit to store user data and want to get push notifications when the records are changed or new records are created. But it does not work...

I register for the subscriptions like this:

- (void) updateCloudSubscriptions {

    NSPredicate *allPredicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
    CKSubscription *newOrUpdateSubscription = [[CKSubscription alloc]
        initWithRecordType:kMyRecordType predicate:allPredicate options:
        (CKSubscriptionOptionsFiresOnRecordCreation | CKSubscriptionOptionsFiresOnRecordUpdate)];
    CKNotificationInfo *newOrUpdateNotificationInfo = [CKNotificationInfo new];
    newOrUpdateNotificationInfo.shouldBadge = NO;
    newOrUpdateNotificationInfo.shouldSendContentAvailable = YES;
    newOrUpdateSubscription.notificationInfo = newOrUpdateNotificationInfo;

    CKDatabase *publicDatabase = [[CKContainer containerWithIdentifier:kMyContainerID] 
        publicCloudDatabase];
    [publicDatabase saveSubscription:newOrUpdateSubscription 
         completionHandler:^(CKSubscription *theSubscription, NSError *saveError) {
        if (saveError){
            //error handling
        }
        NSLog(@"Subscription created");
    }];
}

This succeeds. On the CloudKit Dashboard the subscription is created correctly.

In my AppDelegate I now have the following:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:
        (UIUserNotificationTypeNone | UIUserNotificationTypeAlert |
        UIUserNotificationTypeBadge | UIUserNotificationTypeSound) categories:nil];
    [application registerUserNotificationSettings:notificationSettings];
    [application registerForRemoteNotifications];
}

and these delegate methods implemented:

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    NSLog(@"%@ with token = %@", NSStringFromSelector(_cmd), deviceToken);
}


- (void)application:(UIApplication *)application
    didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"%@ with error = %@", NSStringFromSelector(_cmd), error);
}


- (void)application:(UIApplication *)application 
    didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"%@", NSStringFromSelector(_cmd));
}

didRegisterForRemoteNotificationsWithDeviceTokenis called successfully with a token. But didReceiveRemoteNotification is never called.

I tested this by changing values on the Mac version of my App and on the iPhone version. Both upload the changes but neither triggers a notification. I also tried changing the values directly on the dashboard but that did not cause notifications either.

What am I missing here?

If relevant: I am on OS X 10.10 with XCode 6.4

I activated apsd logging but only get messages like this:

Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Saving database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Destroying database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Closed database.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Reopening database
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Initializing database on thread: <NSThread: 0x7f8f1bf80dd0>{number = 55, name = (null)}
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling auto vacuum.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling WAL journal mode.
Jul 12 18:25:29 Mac.local apsd[44748]: APSMessageStore - Enabling Foreign Key support.
like image 508
codingFriend1 Avatar asked Jul 12 '15 16:07

codingFriend1


2 Answers

Your notification registration is correct for iOS 8, but on OS X you have to use registerForRemoteNotificationTypes: method of NSApplication and on iOS 7 the registerForRemoteNotificationTypes: method of UIApplication. Documentation:

An app must register with Apple Push Notification service (APNs) to receive remote notifications sent by the app’s push provider. In iOS 8 and later, registration has four stages:

  1. Register the notification types your app supports using registerUserNotificationSettings:.
  2. Register to receive push notifications via APNs by calling your app’s registerForRemoteNotifications method.
  3. Store the device token returned to the app delegate by the server for a successful registration, or handle registration failure gracefully.
  4. Forward the device token to the app’s push provider.

(In iOS 7, instead of the first two steps, you register by calling the registerForRemoteNotificationTypes: method of UIApplication, and in OS X by calling the registerForRemoteNotificationTypes: method of NSApplication.)

Also implement didReceiveRemoteNotification:fetchCompletionHandler: instead of didReceiveRemoteNotification:

Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

If you want the notifications to wake your app, make sure to edit Info.plist and check the "Enable Background Modes" and "Remote notifications" check boxes:

enter image description here

Since you want a silent notification, per documentation, you should only send the "content-available" flag to 1, so that's correct. But there are other users that had problems with silent notifications and apparently, sending the "sound" property as an empty string did help (see this question), so you could try to set CKNotificationInfo.soundName to an empty string.

like image 95
Baris Akar Avatar answered Nov 03 '22 08:11

Baris Akar


The 2015 WWDC CloudKit Tips & Tricks video pointed out that if you want to send a silent push notification, you need to set the shouldSendContentAvailable to true on your notificationInfo dictionary, like so:

let notificationInfo = CKNotificationInfo()
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo
like image 20
Dave Browning Avatar answered Nov 03 '22 10:11

Dave Browning