ioscloudkit

How to Share a CloudKit Record with Multiple Participants While Keeping some Individual Records Private to each Participant?


In a CloudKit private database, the Owner creates a custom zone and performs the following actions:

  1. Creates CKRecord1 with CKShare1 and invites Participant1 to it.
  2. Creates CKRecord2 with CKShare2 and invites Participant2 to it.
  3. Creates CKRecordShared, which should be accessible to both Participant1 and Participant2.

How can I achieve step 3?

I observed that:

One potential solution I see is to have the Owner create a separate CKShare for CKRecordShared and share it explicitly with each participant. However, this approach could lead to user errors, as it requires careful management of multiple shares for each participant. For example, if Owner accidentally sent only one invitation to Participant1 OR if Participant1 did not accept both invitations from Owner, then app will not work properly as it will see only subset of intended data.

Is there a better way to handle this scenario, ensuring that CKRecordShared is accessible to multiple participants without introducing unnecessary complexity or potential errors?


Solution

  • CloudKit doesn't really support what you are trying to accomplish. A given CKShare is associated with either an entire record zone or with a single record hierarchy within a record zone. That 'CKSharecan be invited to zero or more participants. Any givenCKRecord` can only have one parent record which means that the record can only belong to a single record hierarchy.

    I only see two (maybe three) possible solutions and neither is ideal.

    1. This is the solution you already mentioned. It would involve a CKShare for the common shared record hierarchy and a CKShare for each hierarchy of "private" shared records. As you've stated, this results in two invitations per share participant with the issue of a given participant only accepting one of the two invitations. Or the user could initially accept both but later opt out of just one, leaving them access to only either the "common" data or just their "private" data.

    2. The other solution would involve duplicating each "common" shared record, once for each participant. Each participant would only need to be invited via a single CKShare for their copy. While this eliminates the problem of having to send each participant multiple share invitations, it causes many other, possibly worse, issues. The database owner now has to maintain a copy of the "common" shared data for each participant. Once one participant updates a record in the share, the owner would need to detect that update and make the same update in all of the other copies for each of the other participants. This is obviously very complicated and prone to error, not to mention very inefficient due to all of the redundancy.

    1. If your app and the "common" shared data will always be available to all users of the app, then you can eliminate all of the problems of the first two solutions by using the public database for the "common" shared data and only use the private database with a CKShare for each participants' "private" shared records. This precludes the need for any data redundancy and only requires one CKShare per participant. But this only works if all users of the app all share one common pool of "common" shared data.

      Even if that isn't true, with a little extra logic, you may be able to still use the public database for multiple sets of "common" shared data. You would need extra logic to ensure the user's copy of the app only shows the user their portion of the data in the public database.

    While I don't see CloudKit being updated to support your needs any time soon, it wouldn't hurt to submit an enhancement request to Apple (via the Feedback app) explaining your needs to allow a single CKShare/invitation to support multiple hierarchies of records instead of just the one it currently supports.