Search code examples
xcodecloudkitsharingckshare

CKShare "userDidAcceptCloudKitShareWith" is only triggered by first installation of same user


in Appdelegate I have userDidAcceptCloudKitShareWith
but it gets only fired for the first device from the user who has accepted the invitation.

Example:

  • User A invites User B.
  • User B accepts the invitation on device B1 -> everything is ok, the method gets fired and I know what to do.
  • The problem is, when user B uses his device B2, the method does not get fired. How am I supposed to know on device B2, that user B has already accepted an invitation?

I tried this with real devices and get only on first device the method fired.

I could check whether he has a sharedZone with the expected zoneID, however this sounds a little strange to me - any help is more than appreciated!


Solution

  • You need to create a subscription to the shared database when your app launches. That way, when a user accepts a share (on any device) the subscription will be triggered and all that user's devices (that have the subscription) will pull down the latest data in that database. It isn't necessary to accept the CKShare on multiple devices.

    Here's an example of how you would create a subscription to the shared database:

    let container = CKContainer(identifier: "...")
    
    let subscription = CKDatabaseSubscription(subscriptionID: "shared")
    let sharedInfo = CKNotificationInfo()
    sharedInfo.shouldSendContentAvailable = true
    sharedInfo.alertBody = "" //This needs to be set or pushes sometimes don't get sent
    subscription.notificationInfo = sharedInfo
    
    let operation = CKModifySubscriptionsOperation(subscriptionsToSave: [subscription], subscriptionIDsToDelete: nil)
    container.sharedCloudDatabase.add(operation)
    

    You will also need to process changes fetched from the shared database to show the new shared data in your app like this:

    let fetchOperation = CKFetchDatabaseChangesOperation()
    fetchOperation.fetchAllChanges = true
    fetchOperation.recordZoneWithIDChangedBlock = { recordZoneID in
      //Process custom/shared zone changes...
    }
    
    container.sharedCloudDatabase.add(fetchOperation)
    

    I hope that helps.