Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why CloudKit notification doesn't arrive when app is installed from testflight while it works when compiled from Xcode?

CloudKit notifications doesn't arrive on production (AppStore, TestFlight), but works in development mode (installed from Xcode).

Why?

This is how I register for remote notifications:

    let center = UNUserNotificationCenter.current()
    
    center.delegate = self
    center.requestAuthorization(options: [.alert, .badge, .sound]) { authorised, error in
        
        DispatchQueue.main.sync {
            application.registerForRemoteNotifications()
        }
    }

and this is how I save subscriptions:

func subscribeForChanges() {
    
    let options: CKQuerySubscriptionOptions = [.firesOnRecordCreation, .firesOnRecordUpdate, .firesOnRecordDeletion]
    
    let serviceSubscription = CKQuerySubscription(recordType: "Service", predicate: NSPredicate(value: true), options: options)
    let goalSubscription = CKQuerySubscription(recordType: "Goal", predicate: NSPredicate(value: true), options: options)
    let territorySubscription = CKQuerySubscription(recordType: "Territory", predicate: NSPredicate(value: true), options: options)
    let addressSubscription = CKQuerySubscription(recordType: "Address", predicate: NSPredicate(value: true), options: options)
    let noteSubscription = CKQuerySubscription(recordType: "Note", predicate: NSPredicate(value: true), options: options)
    let daySubscription = CKQuerySubscription(recordType: "Day", predicate: NSPredicate(value: true), options: options)
    let shareSubscription = CKQuerySubscription(recordType: "cloudkit.share", predicate: NSPredicate(value: true), options: options)
    
    let notificationInfo = CKNotificationInfo()
    notificationInfo.shouldBadge = false
    notificationInfo.shouldSendContentAvailable = true
    
    serviceSubscription.notificationInfo = notificationInfo
    goalSubscription.notificationInfo = notificationInfo
    territorySubscription.notificationInfo = notificationInfo
    addressSubscription.notificationInfo = notificationInfo
    noteSubscription.notificationInfo = notificationInfo
    daySubscription.notificationInfo = notificationInfo
    shareSubscription.notificationInfo = notificationInfo
    
    let privateSubscriptionsOperation = CKModifySubscriptionsOperation(subscriptionsToSave: [serviceSubscription, goalSubscription, territorySubscription, addressSubscription, noteSubscription, daySubscription, shareSubscription], subscriptionIDsToDelete: nil)
    privateSubscriptionsOperation.database = CloudAssistant.shared.privateDatabase
    
    let notificationInfoDatabaseSubscription = CKNotificationInfo()
    notificationInfoDatabaseSubscription.shouldSendContentAvailable = true
    
    let subscription = CKDatabaseSubscription(subscriptionID: "pl.blue-world.fieldservice.sharedDatabase")
    subscription.notificationInfo = notificationInfoDatabaseSubscription
    let sharedSubscriptionsOperation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: nil)
    sharedSubscriptionsOperation.database = CloudAssistant.shared.sharedDatabase

    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1
    queue.addOperation(privateSubscriptionsOperation)
    queue.addOperation(sharedSubscriptionsOperation)
    privateDatabase.save(CKRecordZone(zoneName: "fieldservice")) { _, _ in }
}
like image 216
Bartłomiej Semańczyk Avatar asked Mar 17 '26 20:03

Bartłomiej Semańczyk


1 Answers

When something similar happened to me, it was caused by mixing up the server change tokens between the dev and prod environments. In my case, the dev change token was, say aaabbb, while the prod change token was something earlier, like, aaaaab. Since I was inadvertently using the dev change token, it was "ahead" of prod.

I see you've edited your question, but as I recall from the prior version, I believe you have already configured xcode builds to use the prod env. But, there's a simple test to prove or disprove if this theory is related to your problem. After you app inits in the env where you are not receiving notifs, call

CKFetchNotificationChangesOperation

Using Nil for the server change token. That should return every notif since the very start for that user. If the results include the missing notifs, then the problem is probably in the way you're handling change tokens.

Otherwise, I would dump all subs for that user using

CKFetchSubscriptionOperation

on both an xcode build and a testflight build, and compare the two sets, paying close attention to the predicates. I would expect the lists to be identical since you were already using the prod env, but I would rule this simple test out before looking for more complicated causes.

like image 80
Thunk Avatar answered Mar 19 '26 15:03

Thunk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!