CloudKit CKShare userDidAcceptCloudKit Поделиться с приложением Never Fires on Mac

Я работаю над принятием CKShare в приложении MacOS в Swift 4. Я уже сделал все следующее:

  • Создать CKShare и сохранить его с его rootRecord в CloudKit
  • Добавить участника (CKShare.Participant)
  • Я подтвердил, что CKShare находится на сервере CloudKit, и что приглашенный мной человек имеет к нему доступ. Вот скриншот: https://d.pr/i/0sMFQq

Когда я нажимаю ссылку общего доступа, связанную с CKShare, он открывает мое приложение, но ничего не происходит и userDidAcceptCloudKitShareWith не стреляет

func application(_ application: NSApplication, userDidAcceptCloudKitShareWith metadata: CKShareMetadata) {
  print("Made it!") //<-- This never gets logged :(
  let shareOperation = CKAcceptSharesOperation(shareMetadatas: [metadata])
  shareOperation.qualityOfService = .userInteractive

  shareOperation.perShareCompletionBlock = {meta, share, error in
    print("meta \(meta)\nshare \(share)\nerror \(error)")
  }
  shareOperation.acceptSharesCompletionBlock = { error in
    if let error = error{
      print("error in accept share completion \(error)")
    }else{
      //Send your user to where they need to go in your app
      print("successful share:\n\(metadata)")
    }
  }

  CKContainer.default().add(shareOperation)
}

Есть ли какая-то схема URL, которую я должен включить в мой info.plist? Или, возможно, протокол, которому я должен соответствовать в моем NSApplicationDelegate делегировать? Я не могу при всей жизни понять, что делать. Заранее спасибо!

Обновить

Я попробовал еще несколько вещей на этом. Когда я открываю ссылку общего доступа в веб-браузере, я вижу это:

Нажатие ОК заставляет экран исчезнуть к этому:

Ничего такого

Не особенно полезно.:) После этого статус участника в CloudKit по-прежнему приглашен, поэтому доля еще не принята.

Когда я нажимаю на ссылку общего доступа в сообщениях, я вижу всплывающее окно, как это: CloudKit Sharing Popup После нажатия кнопки "Открыть" в доке появляется новая копия моего приложения, а затем приложение внезапно закрывается. В журнале сбоев говорится:

Завершение работы приложения из-за необработанного исключения "CKException", причина: "В приложении отсутствуют необходимые права com.apple.developer.icloud-services"

Я попытался выключить и снова включить iCloud в разделе "Возможности" XCode, но ничего не изменилось. Я знаю, что это исключение не может быть правильным, потому что я могу нормально запускать свое приложение и использовать CloudKit весь день. Только CKShare вызывает этот сбой.

Это беспорядок. Спаси меня, Оби-Ван Кеноби, ты моя единственная надежда.

5 ответов

Да,

Вы должны добавить это в ваш info.plist.

<key>CKSharingSupported</key>
<true/>

** Отредактированный ответ **

Я использую этот код, чтобы поделиться, я не делаю это вручную... не уверен, должен ли это признак под OS X I признаться. Я использую iOS.

let share = CKShare(rootRecord: record2S!)
share[CKShareTitleKey] = "My Next Share" as CKRecordValue
share.publicPermission = .none

let sharingController = UICloudSharingController(preparationHandler: {(UICloudSharingController, handler:
                    @escaping (CKShare?, CKContainer?, Error?) -> Void) in
let modifyOp = CKModifyRecordsOperation(recordsToSave:
                        [record2S!, share], recordIDsToDelete: nil)
modifyOp.savePolicy = .allKeys
modifyOp.modifyRecordsCompletionBlock = { (record, recordID,
                        error) in
                        handler(share, CKContainer.default(), error)
                    }
                    CKContainer.default().privateCloudDatabase.add(modifyOp)
                })
sharingController.availablePermissions = [.allowReadWrite,
                                                          .allowPrivate]
sharingController.delegate = self
                sharingController.popoverPresentationController?.sourceView = self.view
            DispatchQueue.main.async {
                self.present(sharingController, animated:true, completion:nil)
            }

Здесь представлен контроллер активности, в котором вы можете выбрать, скажем, электронную почту, а затем отправить ссылку. Вы также можете посмотреть это видео, сосредоточившись на cloudKit JS в самом начале.

Посмотрите это видео WWDC https://developer.apple.com/videos/play/wwdc2015/710/ В нем рассказывается о JSON API Cloudkit, используя его, вы можете запрашивать, что было, а что нет, в окне терминала / простой сценарий, возможно. Я сделал то же самое при использовании Dropbox API несколько лет назад. Эй, вы можете даже использовать JSON API cloudkit в своем коде вместо собственных вызовов.

Я наконец получил это на работу! Я сделал все из следующего:

  1. Удалено мое приложение из ~/Library/Developer/Excode/DerivedData
  2. Удостоверился, что у меня нет других копий моего приложения, заархивированных где-либо на моей машине
  3. Сказал молитву.
  4. Rebooted.

Боже, это было грубо.:)

Если вы используете SceneDelegate, реализуйте обратный вызов делегата там, а не на AppDelegate.

func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
    // ...
}

Если ваше приложение представляет собой приложение Mac Catalyst, работающее на любой версии macOS Catalina по крайней мере до 10.15.4 Beta 1 включительно, метод userDidAcceptCloudKitShareWith UIApplicationDelegate никогда не будет вызван.

После некоторой значительной отладки мы обнаружили, что MacCatalyst UIKit даже не имеет реализации для userDidAcceptCloudKitShareWithMetadata в своем делегате UIApplication. Он не сломан, его просто нет. Итак, по крайней мере временно, наш обходной путь заключается в следующем, который, кажется, работает, даже если он очень неэлегантен:

// Add CloudKit sharing acceptance handling to UINSApplicationDelegate, which is missing it.
#if targetEnvironment(macCatalyst)
extension NSObject {
    @objc func application(_ application: NSObject, userDidAcceptCloudKitShareWithMetadata cloudKitShareMetadata: CKShare.Metadata) {
        YourClass.acceptCloudKitShare(cloudKitShareMetadata: cloudKitShareMetadata)
    }
}
#endif

Вам нужно создать делегат приложения для своего приложения SwiftUI, используя @NSApplicationDelegateAdaptor:

      @main
struct Sharing_ServiceApp: App
{
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene
    {
        WindowGroup
        {
            ContentView()
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
        }
    }
}

Я вставил эту строку, и мой код мгновенно начал получать запросы на совместное использование.

Другие вопросы по тегам