UICloudSharingController 不显示/不与 CloudKit 应用程序一起使用

Posted

技术标签:

【中文标题】UICloudSharingController 不显示/不与 CloudKit 应用程序一起使用【英文标题】:UICloudSharingController Does not Display/Work with CloudKit App 【发布时间】:2021-11-07 00:30:51 【问题描述】:

我一直在努力让应用程序与 CloudKit 和记录共享一起工作。我有 为一个用户创建了几个在设备之间同步 Core Data 记录的应用程序。我没有 能够让 UICloudSharingController 用于共享记录。我可以显示 共享视图控制器,但点击邮件或消息显示键盘但没有 地址字段,无法关闭视图。我对此感到非常沮丧,以至于我 决定从基础开始尝试 Apple“共享”示例应用程序。然而 示例应用也不适合我。

以下是示例应用的链接: https://github.com/apple/cloudkit-sample-sharing/tree/swift-concurrency

下面的代码几乎直接来自示例应用程序。

这是 ContentView 文件:

import SwiftUI
import CloudKit

struct ContentView: View 

    @EnvironmentObject private var vm: ViewModel

    @State private var isAddingContact = false
    @State private var isSharing = false
    @State private var isProcessingShare = false

    @State private var showShareView = false
    @State private var showIntermediateView = false

    @State private var activeShare: CKShare?
    @State private var activeContainer: CKContainer?

    var body: some View 
        NavigationView 
            contentView
                .navigationTitle("Contacts")
                .toolbar 
                    ToolbarItem(placement: .navigationBarLeading) 
                        Button  Task.init  try await vm.refresh()   label:  Image(systemName: "arrow.clockwise") 
                    
                    ToolbarItem(placement: .navigationBarLeading) 
                        progressView
                    
                    ToolbarItem(placement: .navigationBarTrailing) 
                        Button(action:  isAddingContact = true )  Image(systemName: "plus") 
                    
                
        
        .onAppear 
            Task.init 
                try await vm.initialize()
                try await vm.refresh()
            
        
        .sheet(isPresented: $isAddingContact, content: 
            AddContactView(onAdd: addContact, onCancel:  isAddingContact = false )
        )
    

    /// This progress view will display when either the ViewModel is loading, or a share is processing.
    var progressView: some View 
        let showProgress: Bool = 
            if case .loading = vm.state 
                return true
             else if isProcessingShare 
                return true
            
            return false
        ()
        return Group 
            if showProgress 
                ProgressView()
            
        
    

    /// Dynamic view built from ViewModel state.
    private var contentView: some View 
        Group 
            switch vm.state 
            case let .loaded(privateContacts, sharedContacts):
                List 
                    Section(header: Text("Private")) 
                        ForEach(privateContacts)  contactRowView(for: $0) 
                    
                    Section(header: Text("Shared")) 
                        ForEach(sharedContacts)  contactRowView(for: $0, shareable: false) 
                    
                .listStyle(GroupedListStyle())
            
            case .error(let error):
                VStack 
                    Text("An error occurred: \(error.localizedDescription)").padding()
                    Spacer()
                
            
            case .loading:
                VStack  EmptyView() 
            
        
    

    /// Builds a `CloudSharingView` with state after processing a share.
    private func shareView() -> CloudSharingView? 

        guard let share = activeShare, let container = activeContainer else 
            return nil
        
    
        return CloudSharingView(container: container, share: share)
    

    /// Builds a Contact row view for display contact information in a List.
    private func contactRowView(for contact: Contact, shareable: Bool = true) -> some View 
        HStack 
            VStack(alignment: .leading) 
                Text(contact.name)
                Text(contact.phoneNumber)
                    .textContentType(.telephoneNumber)
                    .font(.footnote)
            
        
            if shareable 
            
                Spacer()

                Button(action:  Task.init  try? await shareContact(contact) 
                , label:  Image(systemName: "square.and.arrow.up") ).buttonStyle(BorderlessButtonStyle())
                    .sheet(isPresented: $isSharing, content:  shareView() )
            
            //if sharable
        //h
    //contact row view

    // MARK: - Actions

    private func addContact(name: String, phoneNumber: String) async throws 
        try await vm.addContact(name: name, phoneNumber: phoneNumber)
        try await vm.refresh()
        isAddingContact = false
    

    private func shareContact(_ contact: Contact) async throws 
        isProcessingShare = true
    
        do 
            let (share, container) = try await vm.createShare(contact: contact)
            isProcessingShare = false
            activeShare = share
            activeContainer = container
            isSharing = true
         catch 
            debugPrint("Error sharing contact record: \(error)")
        
    

以及共享视图的 UIViewControllerRepresentable 文件:

import Foundation
import SwiftUI
import UIKit
import CloudKit

/// This struct wraps a `UIImagePickerController` for use in SwiftUI.
struct CloudSharingView: UIViewControllerRepresentable 

    @Environment(\.presentationMode) var presentationMode
    let container: CKContainer
    let share: CKShare

    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) 

    func makeUIViewController(context: Context) -> some UIViewController 

        let sharingController = UICloudSharingController(share: share, container: container)
        sharingController.availablePermissions = [.allowReadWrite, .allowPrivate]
        sharingController.delegate = context.coordinator
    
        return sharingController
    

    func makeCoordinator() -> CloudSharingView.Coordinator 
        Coordinator()
    

    final class Coordinator: NSObject, UICloudSharingControllerDelegate 
    
        func cloudSharingController(_ csc: UICloudSharingController, failedToSaveShareWithError error: Error) 
            debugPrint("Error saving share: \(error)")
        

        func itemTitle(for csc: UICloudSharingController) -> String? 
            "Sharing Example"
        
    

这是点击分享记录时显示的屏幕。这一切看起来都符合预期:

这是点击消息后的屏幕(邮件的结果相同)。我没有看到任何影响第二个屏幕演示的方法 - 可表示的视图控制器似乎不适用于此版本的 Xcode:

任何指导将不胜感激。 Xcode 13.1、ios 15 和我在 macOS Monterrey 上。

【问题讨论】:

您好,您解决了这个问题吗? 很遗憾,没有。我把这个项目搁置一旁,直到找到解决办法。 【参考方案1】:

我遇到了同样的问题,并通过更改 CloudSharingView.swift 中的 makeUIViewController() 来解决它:

    func makeUIViewController(context: Context) -> some UIViewController 
        share[CKShare.SystemFieldKey.title] = "Boom"
        let sharingController = UICloudSharingController(share: share, container: container)
        sharingController.availablePermissions = [.allowReadWrite, .allowPrivate]
        sharingController.delegate = context.coordinator
-->>>        sharingController.modalPresentationStyle = .none
        return sharingController
    

似乎有些有价值的工作,有些则不然。不知道为什么。

【讨论】:

哇。难以置信。是的,确实,禁用模态演示的行对我有用。谢谢。

以上是关于UICloudSharingController 不显示/不与 CloudKit 应用程序一起使用的主要内容,如果未能解决你的问题,请参考以下文章

UICloudSharingController 在 Xcode 11 中显示无限活动指示

UICloudSharingController 不显示/不与 CloudKit 应用程序一起使用

无法共享 CloudKit CKShare 记录