【发布时间】:2019-12-07 22:27:52
【问题描述】:
我有一个使用 SwiftUI 的项目需要共享 CloudKit,但我无法让 UICloudSharingController 在 SwiftUI 环境中正常运行。
第一个问题
使用UIViewControllerRepresentable 直接包装UICloudSharingController 会产生一个无限旋转器(请参阅this)。正如对UIActivityViewController 等其他系统控制器所做的那样,我将UICloudSharingController 包装在包含UIViewController 中,如下所示:
struct CloudSharingController: UIViewControllerRepresentable {
@EnvironmentObject var store: CloudStore
@Binding var isShowing: Bool
func makeUIViewController(context: Context) -> CloudControllerHost {
let host = CloudControllerHost()
host.rootRecord = store.noteRecord
host.container = store.container
return host
}
func updateUIViewController(_ host: CloudControllerHost, context: Context) {
if isShowing, host.isPresented == false {
host.share()
}
}
}
final class CloudControllerHost: UIViewController {
var rootRecord: CKRecord? = nil
var container: CKContainer = .default()
var isPresented = false
func share() {
let sharingController = shareController
isPresented = true
present(sharingController, animated: true, completion: nil)
}
lazy var shareController: UICloudSharingController = {
let controller = UICloudSharingController { [weak self] controller, completion in
guard let self = self else { return completion(nil, nil, CloudError.controllerInvalidated) }
guard let record = self.rootRecord else { return completion(nil, nil, CloudError.missingNoteRecord) }
let share = CKShare(rootRecord: record)
let operation = CKModifyRecordsOperation(recordsToSave: [record, share], recordIDsToDelete: [])
operation.modifyRecordsCompletionBlock = { saved, _, error in
if let error = error {
return completion(nil, nil, error)
}
completion(share, self.container, nil)
}
self.container.privateCloudDatabase.add(operation)
}
controller.delegate = self
controller.popoverPresentationController?.sourceView = self.view
return controller
}()
}
这可以让控制器正常启动,但是...
第二个问题
点击关闭按钮或滑动关闭,控制器将消失,但没有通知它已被关闭。开始呈现控制器的 SwiftUI 视图的 @State 属性仍然是 true。没有明显的方法来检测模式的解除。经过一些实验,我发现呈现控制器是在SceneDelegate 中创建的原始UIHostingController。通过一些hackery,您可以将UIHostingController 子类中引用的对象注入CloudSharingController。这将让您检测解雇并将@State 属性设置为false。但是,所有导航栏按钮在关闭后都不再起作用,因此您只能点击这个东西一次。场景的其余部分功能齐全,但导航栏中的按钮没有响应。
第三个问题
即使您可以让UICloudSharingController 正常显示和关闭,点击任何共享方法(消息、邮件等)也会使控制器消失且没有动画,而用于共享 URL 的控制器不会' t上来。没有崩溃或控制台消息——它只是消失了。
演示
我在 GitHub 上做了一个快速而肮脏的项目来演示这个问题:CloudKitSharing。它只创建一个String 和一个CKRecord 来使用CloudKit 来表示它。界面显示String(一个UUID),带有一个导航栏按钮来分享它:
恳求
有什么方法可以在 SwiftUI 中使用 UICloudSharingController 吗?没有时间在 UIKit 或自定义共享控制器中重建项目(我知道——处于最前沿的代价????)
【问题讨论】: