So, I'm using CloudKit to store Posts for a social media app I'm building. A post has a username called a 'Plate', and I would like users to be able to get notified when a Post is created with a specified Plate. I'm using CloudKit Query Subscriptions to do this, but I'm getting some problems.
The user can press a button to create the subscription, and I can see (in the CloudKit dashboard) that the subscription has been created successfully. But when I create a record, the push notification is never sent.
Weirdly, the notifications used to work but stopped seemingly randomly.
Some debugging I've already done:
- I am using a different iCloud account to create the record than to get the notification
- The subscription is created on a physical device (not a simulator)
- I have tried setting the Predicate to a TRUEPREDICATE to eliminate issues with that
- I have requested (and been granted) permission to send push notifications
- I have registered for remote notifications (and it has done this successfully)
- My Notification Info has values (at least one of its values is not null)
- I tried changing the options to .firesOnRecordUpdate (and this worked briefly but stopped for some reason, currently only .firesOnRecordDelete works)
When I get a notification for .firesOnRecordDelete, the notification pops up very briefly and disappears (and the badge number is on something like 28 but then immediately disappears as well)
UPDATE: .firesOnRecordDeletion no longer works either
Here is the code I use to create the subscription:
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if error == nil {
let container = CKContainer.init(identifier: "MY CONTAINER ID")
let publicDatabase = container.publicCloudDatabase
let predicate = NSPredicate(value: true)
let subscription = CKQuerySubscription(recordType: "Post", predicate: predicate, options: [.firesOnRecordCreation])
let notificationInfo = CKSubscription.NotificationInfo()
notificationInfo.title = "New post for " + self.selectedPlate! // selectedPlate is just a string
notificationInfo.shouldSendContentAvailable = true
notificationInfo.soundName = "default"
notificationInfo.desiredKeys = ["Plate"]
notificationInfo.alertBody = "Someone posted something against a number plate you're interested in."
notificationInfo.shouldBadge = false
subscription.notificationInfo = notificationInfo
publicDatabase.save(subscription) { result, error in
print("subscription save")
if let error = error {
print("subscription error" + error.localizedDescription)
} else {
print("subscription saved")
print(result)
}
}
} else {
print(error)
}
}
Heres how I register for Remote Notifications (and I can see it is registered) :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
application.applicationIconBadgeNumber = 0
application.registerForRemoteNotifications()
UNUserNotificationCenter.current().delegate = self
print("is registered = " + String(describing: application.isRegisteredForRemoteNotifications))
}
Here is how I handle the remote Notification (I was going to change this when the notifications were working):
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(.noData)
}
Here is my user notifications willPresent function:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .badge])
}
I've been trying to fix this for weeks, I appreciate any suggestions :)