Search code examples
ioscloudkitios13tvos13

iOS 13.1 doesn't receive silent CKQuerySubscription notifications


My app uses CloudKit Query subscriptions and notifications as part of a CloudKit-based synchronization solution. This works perfectly with iOS 12, macOS 10.14 and even macOS 10.15 beta, but NOT with iOS 13.0, iOS 13.1, iPadOS 13.1 and tvOS 13.0.

Removing and recreating the subscriptions doesn't solve this.

Is this a known problem?

According to the documentation, nothing has changed with CloudKit subscriptions. Or did I miss something?


Solution

  • To receive silent CKQuerySubscription notifications in iOS 13.x and tvOS 13.x, the soundName and alertBody parameters of the NotificationInfo of your CKQuerySubscription must not be set.

    In the past we have learned to use an empty string for said parameters, to make the whole CloudKit subscription thing working, but that's now history. Apparently Apple has fixed an old bug, causing problems with apps that used this 'workaround'.

    I have tested this on iOS 12.4.2, iOS 13.1.2, tvOS 13.0, macOS 10.14.6 and macOS 10.15 GM.

    let info = CKSubscription.NotificationInfo()
    info.shouldSendContentAvailable = true
    // info.soundName = "" // Don't set this property
    // info.alertBody = "" // And also leave this this property alone
    let subscription = CKQuerySubscription(recordType: "yourRecordType", predicate: NSPredicate(value: true), subscriptionID: "yourSubscription", options: [CKQuerySubscription.Options.firesOnRecordUpdate, CKQuerySubscription.Options.firesOnRecordDeletion])
    subscription.notificationInfo = info
    
    // You must first delete the old subscription to change the sound name            
    let deleteOperation = CKModifySubscriptionsOperation(subscriptionsToSave: nil, subscriptionIDsToDelete: ["yourSubscription"])      
    yourContainer.privateCloudDatabase.add(deleteOperation)
    
    let createOperation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: nil)
    createOperation.addDependency(deleteOperation)        
    yourContainer.privateCloudDatabase.add(createOperation)