CKShare and SwiftUI

Hi


Thank you for taking the time to read this post. I am pretty new to coding, so maybe my issues trying to implement CKShare with SwiftUI are due to a basic concept understanding, but I have been working on this for a few days and I can´t figure it out on my own.


I would like to share a CKRecord on a custom zone of a user's private database. I would rather not use Apple's standard screens for adding and removing people (UICloudSharingController) as I found it doesn't match with my users' natural journey.


I coded the lines below to User1 to create a CKShare and include as participants the CKUserIdentit of User2. I then captured the url for User2, so they can accept the share.


On the Cloudkit dashboard, I can see the "cloudkit.share" type record on the User1's private database. User2 does appear on the Sharing Participants Field as Type: User and Acceptance: Invited.


However, once User2 opens the url on a browser as an iCloud registered user, the following error is shown:

iCloud has stopped responding

REPORTED ERROR TITLE A non-empty string is required.

REPORTED ERROR TYPE UNHANDLED_EXCEPTION

ERROR CONTEXT undefined


Has anyone dealt with something similar before? Is there any other way to include a known app's user on a CKShare?


Thank you in advance for your help.


Here my code:


let share = CKShare(rootRecord: recordEquipo)
share[CKShare.SystemFieldKey.title] = "Equipo" as CKRecordValue?
share[CKShare.SystemFieldKey.shareType] = "Some type" as CKRecordValue?
let fetchParticipantsOperation: CKFetchShareParticipantsOperation = CKFetchShareParticipantsOperation(userIdentityLookupInfos: [CKUserIdentity.LookupInfo(emailAddress: DTMemail)] )
fetchParticipantsOperation.fetchShareParticipantsCompletionBlock = {error in
  if let error = error {
  print("error for completion" + error.localizedDescription)
  DispatchQueue.main.async {
  completion(.failure(error))
  }
  }
}
fetchParticipantsOperation.shareParticipantFetchedBlock = {participant in
  participant.permission = .readWrite
  share.addParticipant(participant)
  let modifyOperation: CKModifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: [recordEquipo, share], recordIDsToDelete: nil)
  modifyOperation.savePolicy = .ifServerRecordUnchanged
  modifyOperation.perRecordCompletionBlock = {record, error in
  if let error = error {
  print("error for completion" + error.localizedDescription)
  completion(.failure(error))
  }
  }
  modifyOperation.modifyRecordsCompletionBlock = {records, recordIDs, error in
  guard let ckrecords: [CKRecord] = records, let _: CKRecord = ckrecords.first, error == nil else {
  print("error in modifying the records " + error!.localizedDescription)
  completion(.failure(error!))
  return
  }
  if (share.url != nil) {
  completion(.success(share.url!))}

  }

  baseDatosPrivada.add(modifyOperation)
}
contenedor.add(fetchParticipantsOperation)

Replies

Once you have the share's URL, it can be accepted from a device that User2 is logged in on in two main ways:
  1. User2 taps/clicks on the share URL on an iOS/macOS device that has your app installed: then the system will launch your app with a delegate callback which contains the CKShareMetadata corresponding to the share. Your app can then pass that share metadata to a CKAcceptSharesOperation to accept the share.

  2. You transport the URL directly to your app on User2's device via a side-band channel: in this case you will need to first pass the share URL to a CKFetchShareMetadataOperation to get the share's CKShareMetadata and then proceed to accept the share like in (1)

For more info, refer to the building your own sharing UI sections of this talk:
https://developer.apple.com/videos/play/wwdc2016/226/

The delegate callbacks are documented here:
https://developer.apple.com/documentation/uikit/uiapplicationdelegate/2206721-application
https://developer.apple.com/documentation/appkit/nsapplicationdelegate/2138329-application