CloudKit notifications not being received on iOS device

I have an app on the App Store that works with CloudKit, and remote notifications work just fine there. If a user modifies a record, it triggers a push notification on his/her other devices, and AppDelegate's

didReceiveRemoteNotification
is called.

In the dev environment, I've added some new entities, but in my testing, the push notifications aren't being received anymore. Basically

didReceiveRemoteNotification
isn't being called at all.

Some important notes:

  • this only doesn't work on iOS ... on my Mac app, pointing to the same CloudKit container, the remote notifications are received correctly, so it's nothing to do with how the CloudKit subscription is created or modified (I haven't changed anything in that regards anyways)
  • I do call
    registerForRemoteNotifications
    as before, and
    didRegisterForRemoteNotificationsWithDeviceToken
    is called as expected
  • I am testing on a device, not a simulator
  • Background App Refresh is enabled on the device
  • Notifications are allowed for the app
  • The CKNotificationInfo object is created with
    shouldSendContentAvailable
    = YES, and
    alertBody
    = @"" (not a nil string)

I dug into the device's console logs, using Xcode, and found that the console does output something that suggests that the device is receiving the push notification, but it's not being passed onto the app for some reason:


default 18:02:47.127117 -0800 SpringBoard Received incoming message on topic com.apple.icloud-container.com.ztest.myapp at priority 10
default 18:02:47.133708 -0800 SpringBoard [com.ztest.myapp] Received remote notification request 0E01-5E4D [ waking: 0, hasAlertContent: 0, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Alert]
default 18:02:47.133780 -0800 SpringBoard [com.ztest.myapp] Process delivery of push notification 0E01-5E4D
error 18:02:47.133851 -0800 SpringBoard [com.ztest.myapp] NOT requesting DUET deliver content-availateston-notifiying push notification 0E01-5E4D [pushType: Alert willNotifyUser: 0]
error 18:02:47.133997 -0800 SpringBoard [com.ztest.myapp] NOT delivering non-notifying push notification 0E01-5E4D [pushType: Alert willNotifyUser: 0]
default 18:02:47.134053 -0800 SpringBoard Getting effectiveSectionInfo for section identifier: com.zsquare.ijournal
default 18:02:47.134099 -0800 SpringBoard [com.ztest.myapp] Getting effective section info
default 18:02:47.135743 -0800 SpringBoard [com.ztest.myapp] Got effective section info [ hasResult: 1 ]


I'm not really sure, but it seems like the one line here that shows 'error' with "NOT delivering non-notifying push notification" would explain the problem. But I'm not sure what is causing this. Could it just be the dev environment being flaky? I've tried this on multiple iOS devices now, so it's not just a problem with this one device.


Can anyone suggest any reasons why the push notification isn't being received in the app, or suggest some way to test this and narrow down what's happening?


Thanks.

Replies

If your device is not getting the push notification then you could explore the CloudKit Dashboard to check to see if it is being sent. I found that bugs on Apple's side limited push notifications to the latest 200 subscribers. Using the Bug Reporter, they corrected that error on their end.


But it seems like your device is receiving the notitifcation. (Keep in mind the device that caused the subscription to fire by affecting a change in a CloudKit file does not get/display a notification.) Check the settings in the Settings App allows the device to receive notitifcations.


I assume you have done this stuff:


UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
    [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound + UNAuthorizationOptionBadge)
            completionHandler:^(BOOL granted, NSError * _Nullable error) {
                if(error){
                }else if(granted){
                    dispatch_async(dispatch_get_main_queue(), ^{
                                      //added the if clause after testflight 1
                    if(![[UIApplication sharedApplication] isRegisteredForRemoteNotifications])
                        [[UIApplication sharedApplication] registerForRemoteNotifications];
                    });
                }else{
                    dispatch_async(dispatch_get_main_queue(), ^{
                         // issue and alert message   "you have NOT AUTHORIZED THIS DEVICE 
                       //                  TO RECEIVE THOSE ALERTS.  To authorize this device, tap 
                       //             Launch Settings App below, tap App Name tap Notifications, and then tap 
                        //                       Allow Notifications
                    });
                }
        }];

Thanks for the comments. Yes, I do call UNUserNotificationCenter's requestAuthorizationWithOptions (with alert and sound, but not badge), and if granted, I call registerForRemoteNotifications. The didRegisterForRemoteNotificationsWithDeviceToken is also called. The CloudKit dashboard shows that a push notification is generated. As I mentioned, even the iPhone's console logs seem to show that Springboard receives the notification ... it shows "Received remote notification request 0E01-5E4D [ waking: 0, hasAlertContent: 0, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Alert]"


... but it just doesn't seem to pass it forward to the app. It says "NOT delivering non-notifying push notification 0E01-5E4D [pushType: Alert willNotifyUser: 0]"


Strangely, it works fine on the Mac app, which is pointing to the same private CloudKit database and uses the same CloudKit subscription.


Any thoughts? Could app signing have anything to do with this? I do have the CloudKit and Push Notifications capabilities enabled in the Xcode project file, but I generate manual provisioning profiles for the iOS app vs automatic provisioning for the Mac app. But the profiles are valid for "Development" when I'm testing this.

Turns out, it was an iOS13 problem, and wasn't working on the Release version either. Apparently, Apple changed the behavior so that when you setup a CKSubscription, the CKNotificationInfo's

alertBody
property should be
nil
, instead of an empty string, which is what you needed to do to get notifications to work before. I did have to recreate the subscription, but it works now. Even the device console now shows this:


Received remote notification request DB7E-4D9E [ waking: 0, hasAlertContent: 0, hasSound: 0 hasBadge: 0 hasContentAvailable: 1 hasMutableContent: 0 pushType: Background]
Process delivery of push notification DB7E-4D9E
Request DUET delivers content-available push notification to application



And then the app's didReceiveRemoteNotification (finally) gets called!

Good to know. Is this a silent notification?

yes, it's meant to be a silent notification.

With Catalina 10.15.3 (19D76) I stopped receiving silent notifications using the alertBody = nil. IOS works fine. Anyone else ?

Could you please explain more how can I achieve the same behavior using the FCM JSON request?