0

I had push notifications from CloudKit working and I'm afraid I've done something to break them. If anyone can see something I don't, please help.

When the app launches, I call setupSubscriptions(), which has this code:

let predicate = NSPredicate(value: true)
let subscriptionID = "public-new-changes-deleted"
let subscription = CKQuerySubscription(recordType: recordType, predicate: predicate, subscriptionID: subscriptionID, options: [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion])
let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.shouldSendContentAvailable = true
subscription.notificationInfo = notificationInfo

publicDB.save(subscription) { subscription, error in
if error != nil {
    print("subscription was set up")
}

The setup message does fire. I've also tried making the notificationInfo CKQuerySubscription.NotificationInfo, but there's no discernible difference whether it's that or CKSubscription.

In my app delegate:

application.registerForRemoteNotifications()

I do get a message from application(_ application:, didRegisterForRemoteNotificationsWithDeviceToken:) that the application has registered for notifications.

Then I have:

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("application did receive remote notification")
}

Next I got to my CloudKit Dashboard and create, modify, or delete a record but nothing happens. I'd expect a message from didReceiveRemoteNotification. but nothing. This was working earlier but I can't think of what I changed to break it.

I can create records there and query for them in the app, so I'm sure it's able to see them, but I can't get a push when they're altered.

Other stuff:

In my target's Capabilities tab:

  • Background Fetch and Remote Notifications are both checked under Background Modes.
  • iCloud is on and it's using the correct container -- I can do fetches just fine from CloudKit using the same recordType and publicDB CKDatabase object.
  • Push Notifications are turned on and my entitlements file has a flag for "APS Environment" with a value of development.

On my Apple Developer account page, under the App ID, iCloud and Push Notifications both have green lights for both "Development" and "Distribution."

I can see in the CloudKit dashboard that the subscription types are created once the app's been run.

I'm testing on a device, not in the simulator.

I've tried:

  • Changing whether I create the subscription before or after I register for notifications.
  • Adding a message body, alert sound, and shouldBadge, and requesting notifications using UNUserNotificationCenter, and making the App Delegate a UNUserNotificationCenterDelegate. I get the prompt when I first run the app but the notifications don't arrive.
  • Splitting the subscriptions up into one for .firesOnRecordCreation and one for update and delete.
  • Adding the subscriptions using a CKModifySubscriptionsOperation instead of the database's save method.

Please let me know if you have any ideas. Thank you.

davextreme
  • 995
  • 9
  • 23
  • Is the log in the CloudKit Dashboard showing that the notification is being sent? Have you tried deleting your app and restarting the device? – Clifton Labrum Mar 09 '19 at 17:26
  • I checked the log and do see an entry of type "push" for the Sandbox APNS environment. There's also a log message for the subscription creation and the user matches that of the push. – davextreme Mar 11 '19 at 16:02
  • I list a few other things you can try in this answer: https://stackoverflow.com/questions/52179137/appdelegate-never-gets-its-didreceiveremotenotification-called-for-ckquerysubscr/52193499#52193499 – Clifton Labrum Mar 11 '19 at 16:10
  • 2
    Thank you. An update: I loaded the app onto two different iPads without changing any code, and pushes work fine on each. It might be something with the iPhone. I may wipe it and try again, but at least I can move on for the time being even if I don't know why it wasn't working on the phone. – davextreme Mar 11 '19 at 20:34
  • What type of CKRecord did you use? I find what pushes work better if the type of record is Byte or Asset, so I just serialize my NSString to NSData and save it in iCloudDB. After this strange hack pushes work much better. At least if we use a private database. Also, Apple guarantees to deliver only one(last?) notification in case if the connection is weak or the device not connected. – Ku6ep Feb 28 '20 at 11:28

0 Answers0