0

我试图让我的应用程序的用户能够检索到他们已经共享的记录的 iCloud 共享链接。在创建共享时,我可以使用let share = CKShare(rootRecord: CKRecord)Apple 的UISharingController. 但是,每次我使用这种方法时,旧链接都会失效,并将其他人踢出他们已经加入的共享。如何允许用户(记录所有者)随时获取记录CKShare对象的可共享 URL?

//Initially shares the record
let share = CKShare(rootRecord: newRecord)
share[CKShare.SystemFieldKey.title] = "Group" as CKRecordValue?        
let modifyRecordsOperation = CKModifyRecordsOperation( recordsToSave: [newRecord, share], recordIDsToDelete: nil)

//Activates the UISharingController (code not shown)
4

2 回答 2

1

假设记录已被共享,您可以通过以下方式获取邀请其他参与者的 URL:

if let shareReference = record.share {
    database.fetch(withRecordID: shareReference.recordID) { (share, error) in
        let shareURL = (share as? CKShare)?.url
    }
}

如果您想UICloudSharingController再次显示现有共享(不生成新 URL),您可以执行以下操作:

let sharingController = UICloudSharingController { (_, prepareCompletionHandler) in

    func createNewShare() {
        let operationQueue = OperationQueue()
        operationQueue.maxConcurrentOperationCount = 1

        let share = CKShare(rootRecord: record)
        share[CKShare.SystemFieldKey.title] = "Title" as CKRecordValue
        share.publicPermission = .readWrite

        let modifyRecordsOp = CKModifyRecordsOperation(recordsToSave: [share, record], recordIDsToDelete: nil)
        modifyRecordsOp.modifyRecordsCompletionBlock = { records, recordIDs, error in
            prepareCompletionHandler(share, self, error)
        }
        modifyRecordsOp.database = database
        operationQueue.addOperation(modifyRecordsOp)
    }

    if let shareReference = record.share {
        database.fetch(withRecordID: shareReference.recordID) { (share, error) in
            guard let share = share as? CKShare else {
                createNewShare()
                return
            }
            prepareCompletionHandler(share, self, nil)
        }
    } else {
        createNewShare()
    }
}
于 2020-12-22T21:20:18.267 回答
-1

听起来您在这里遇到了多个问题。我建议仔细阅读 UICloudSharingController文档

第一个问题是在您提供的代码中,您每次都在创建一个新共享,而您想要做的是创建一次,然后在您想要与之交互的任何时候显示该共享(包括获取共享网址)。创建共享后,您可能希望以某种方式将其保存在设备上(就像将其存储在 UserDefaults 中一样简单)。

第二个问题是听起来您没有正确实例化 UICloudSharingController。当您最初创建 CKShare 时,您必须使用 UICloudSharingController init(preparationHandler:)初始化程序并在其中创建共享。

根据不同初始化程序的文档(强调我的):

重要的

您必须使用正确的初始化 方法初始化控制器。如果 CKRecord 已共享,请勿使用 init(preparationHandler:)。同样,如果 CKRecord 未共享,请不要使用 init(share:container:)。保存记录时使用错误的初始化程序会导致错误。

然后,当您想要显示 shareSheet 时,您使用 UICloudSharingController init(share:container:)初始化程序,并将您持久保存到设备的共享提供给它。

这是 UICloudSharingController 文档中提供的用于创建 CKShare 的代码:

func presentCloudSharingController(_ sender: Any) {  guard
    let barButtonItem = sender as? UIBarButtonItem,
    let rootRecord = self.recordToShare else {
    return
  }

  let cloudSharingController = UICloudSharingController { [weak self] (controller, completion: @escaping (CKShare?, CKContainer?, Error?) -> Void) in
    guard let `self` = self else {
      return
    }
    self.share(rootRecord: rootRecord, completion: completion)
  }

  if let popover = cloudSharingController.popoverPresentationController {
    popover.barButtonItem = barButtonItem
  }
  self.present(cloudSharingController, animated: true) {}
}

func share(rootRecord: CKRecord, completion: @escaping (CKShare?, CKContainer?, Error?) -> Void) {
  let shareRecord = CKShare(rootRecord: rootRecord)
  let recordsToSave = [rootRecord, shareRecord];
  let container = CKContainer.default()
  let privateDatabase = container.privateCloudDatabase
  let operation = CKModifyRecordsOperation(recordsToSave: recordsToSave, recordIDsToDelete: []) 
  operation.perRecordCompletionBlock = { (record, error) in
    if let error = error {
      print("CloudKit error: \(error.localizedDescription)")
    }
  }

  operation.modifyRecordsCompletionBlock = { (savedRecords, deletedRecordIDs, error) in
    if let error = error {
      completion(nil, nil, error)
    } else {
      completion(shareRecord, container, nil)
    }
  }

  privateDatabase.add(operation)
}

下次你想展示它时,它会更加直截了当:

 let share = // yourCKShare
 let container = // yourCKContainer
 let viewController = // yourViewController
 let shareController = UICloudSharingController(share: share, container: container)
 viewController.present(shareController, animated: true)

最后要回答您问题的 URL 部分,UICloudSharingController 用于所有内容共享 - 当控制器呈现共享时,所有者可以使用“复制链接”按钮(如果您允许公开,也可能是用户访问 - 我没有看过,因为我的东西是私人的):

在此处输入图像描述

于 2019-04-09T23:06:10.353 回答