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 по-прежнему приглашен, поэтому доля еще не принята.
Когда я нажимаю на ссылку общего доступа в сообщениях, я вижу всплывающее окно, как это: После нажатия кнопки "Открыть" в доке появляется новая копия моего приложения, а затем приложение внезапно закрывается. В журнале сбоев говорится:
Завершение работы приложения из-за необработанного исключения "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 в своем коде вместо собственных вызовов.
Я наконец получил это на работу! Я сделал все из следующего:
- Удалено мое приложение из
~/Library/Developer/Excode/DerivedData
- Удостоверился, что у меня нет других копий моего приложения, заархивированных где-либо на моей машине
- Сказал молитву.
- 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)
}
}
}
Я вставил эту строку, и мой код мгновенно начал получать запросы на совместное использование.