首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用UIApplicationDelegateAdaptor从userDidAcceptCloudKitShareWith获取不起作用的回调

使用UIApplicationDelegateAdaptor从userDidAcceptCloudKitShareWith获取不起作用的回调
EN

Stack Overflow用户
提问于 2021-05-15 06:04:52
回答 2查看 551关注 0票数 5

我正在尝试在userDidAcceptCloudKitShareWith被调用时得到通知。传统上,这是在App Delegate中调用的,但因为我使用App作为根对象来构建一个iOS 14+。到目前为止,我还找不到任何关于如何将userDidAcceptCloudKitShareWith添加到我的应用程序类中的文档,所以我使用UIApplicationDelegateAdaptor来使用App Delegate类,但是似乎userDidAcceptCloudKitShareWith从未被调用过?

代码语言:javascript
复制
import SwiftUI
import CloudKit

// Our observable object class
class ShareDataStore: ObservableObject {
    
    static let shared = ShareDataStore() 
    @Published var didRecieveShare = false
    @Published var shareInfo = ""
}

@main
struct SocialTestAppApp: App {
    
    
    @StateObject var shareDataStore = ShareDataStore.shared 
    
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(shareDataStore)
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
    
    let container = CKContainer(identifier: "iCloud.com.TestApp")
    
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        print("did finish launching called")
        return true
    }
    
    
    func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShare.Metadata) {
        print("delegate callback called!! ")
        acceptShare(metadata: cloudKitShareMetadata) { result in
            switch result {
            case .success(let recordID):
                print("successful share!")
                ShareDataStore.shared.didRecieveShare = true
                ShareDataStore.shared.shareInfo = recordID.recordName
            case .failure(let error):
                print("failure in share = \(error)")
            }
        }    }
    
    func acceptShare(metadata: CKShare.Metadata,
                     completion: @escaping (Result<CKRecord.ID, Error>) -> Void) {
        
        // Create a reference to the share's container so the operation
        // executes in the correct context.
        let container = CKContainer(identifier: metadata.containerIdentifier)
        
        // Create the operation using the metadata the caller provides.
        let operation = CKAcceptSharesOperation(shareMetadatas: [metadata])
        
        var rootRecordID: CKRecord.ID!
        // If CloudKit accepts the share, cache the root record's ID.
        // The completion closure handles any errors.
        operation.perShareCompletionBlock = { metadata, share, error in
            if let _ = share, error == nil {
                rootRecordID = metadata.rootRecordID
            }
        }
        
        // If the operation fails, return the error to the caller.
        // Otherwise, return the record ID of the share's root record.
        operation.acceptSharesCompletionBlock = { error in
            if let error = error {
                completion(.failure(error))
            } else {
                completion(.success(rootRecordID))
            }
        }
        
        // Set an appropriate QoS and add the operation to the
        // container's queue to execute it.
        operation.qualityOfService = .utility
        container.add(operation)
    }
    
    
}

根据Asperi的答案更新:

代码语言:javascript
复制
import SwiftUI
import CloudKit

class ShareDataStore: ObservableObject {
    
    static let shared = ShareDataStore() 
    
    @Published var didRecieveShare = false
    @Published var shareInfo = ""
}

@main
struct athlyticSocialTestAppApp: App {
    
    
    @StateObject var shareDataStore = ShareDataStore.shared 
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    let sceneDelegate = MySceneDelegate()
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(shareDataStore)
                 .withHostingWindow { window in
                 sceneDelegate.originalDelegate = window.windowScene.delegate
                 window.windowScene.delegate = sceneDelegate
              }
        }
        
    }
    
}


class MySceneDelegate: NSObject, UIWindowSceneDelegate {

    let container = CKContainer(identifier: "iCloud.com...")
    
     var originalDelegate: UIWindowSceneDelegate?

        var window: UIWindow?

        func sceneWillEnterForeground(_ scene: UIScene) {
            print("scene is active")
        }

        func sceneWillResignActive(_ scene: UIScene) {
            print("scene will resign active")
        }
        
    
      // forward all other UIWindowSceneDelegate/UISceneDelegate callbacks to original, like
   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    originalDelegate?.scene!(scene, willConnectTo: session, options: connectionOptions)
   }

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

            print("delegate callback called!! ")
            acceptShare(metadata: cloudKitShareMetadata) { result in
                switch result {
                case .success(let recordID):
                    print("successful share!")
                    ShareDataStore.shared.didRecieveShare = true
                    ShareDataStore.shared.shareInfo = recordID.recordName
                case .failure(let error):
                    print("failure in share = \(error)")
                }
            }

        }

}


extension View {
    func withHostingWindow(_ callback: @escaping (UIWindow?) -> Void) -> some View {
        self.background(HostingWindowFinder(callback: callback))
    }
}

struct HostingWindowFinder: UIViewRepresentable {
    var callback: (UIWindow?) -> ()

    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        DispatchQueue.main.async { [weak view] in
            self.callback(view?.window)
        }
        return view
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-05-23 14:05:16

Scene-based应用程序中,userDidAcceptCloudKitShareWith回调被发送到场景代理,但在SwiftUI 2.0 App-based应用程序中,场景代理由SwiftUI本身用于提供scenePhase事件,但不提供处理主题回调的本机方法。

解决此问题的可能方法是找到一个窗口并注入自己的场景代理包装,该包装将处理userDidAcceptCloudKitShareWith并将其他代理转发给原始SwiftUI委托(以保持标准SwiftUI事件工作)。

下面是几个基于https://stackoverflow.com/a/63276688/12299030窗口访问的演示快照(不过,您也可以使用任何其他更好的方法来获取窗口)

代码语言:javascript
复制
@main
struct athlyticSocialTestAppApp: App {
    @StateObject var shareDataStore = ShareDataStore.shared 
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    let sceneDelegate = MySceneDelegate()
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(shareDataStore)
              .withHostingWindow { window in
                 sceneDelegate.originalDelegate = window?.windowScene.delegate
                 window?.windowScene.delegate = sceneDelegate
              }
        }
    }
}

class MySceneDelegate : NSObject, UIWindowSceneDelegate {
   var originalDelegate: UISceneDelegate?

   func windowScene(_ windowScene: UIWindowScene, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {

       // your code here
   }

   // forward all other UIWindowSceneDelegate/UISceneDelegate callbacks to original, like
   func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
       originalDelegate?.scene(scene, willConnectTo: session, options: connectionOptions)
   }
}
票数 5
EN

Stack Overflow用户

发布于 2021-05-19 08:42:36

看看这个问题,它有很多有用的东西,可以通过几个可能的答案来检查:

CloudKit CKShare userDidAcceptCloudKitShareWith Never Fires on Mac App

确保将CKSharingSupported密钥添加到您的info.plist中,然后尝试使用上面链接中的答案将userDidAcceptCloudKitShareWith放在不同的位置(放置位置将取决于您正在构建的应用程序的类型)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67541441

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档