簡體   English   中英

將數據從委托 Swift Class 傳遞到 SwiftUI 結構中的 EnvironmentObject

[英]Passing Data from Delegate Swift Class to EnvironmentObject in SwiftUI Struct

如何將來自 Swift class 中的委托觸發的方法的傳入數據傳遞給 EnvironmentObject?

I am aware that for this to work my Swift class needs to be called/initialized from the SwiftUI struct (be a child of the parent SwiftUI struct). 但是,我在 Apple Watch 應用程序的 ExtensionDelegate 中初始化了我的 Swift class。 我希望在名稱更新時看到 UI 文本元素發生變化。

以下代碼在 Apple Watch 上運行:

class User: ObservableObject {
    
    @Published var id: UUID?
    @Published var name: String?
}
//SwiftUI struct
struct UI: View {

@EnvironmentObject var userEnv: User

var body: some View {
   Text(userEnv.name)
 }
}
// Swift class
class WatchConnectivityProvider: NSObject, WCSessionDelegate {

 static let shared = WatchConnectivityProvider()
 private let session: WCSession
    
    init(session: WCSession = .default) {
        self.session = session
        super.init()
    }
    
    func activateSession() {
        if WCSession.isSupported() {
            session.delegate = self
            session.activate()
        }
    }

    //This func gets triggered when data is sent from the iPhone
    func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
        
        let list = message["list"]
        
        let jsonDecoder = JSONDecoder()
        if let data = try? jsonDecoder.decode(User.self, from: list as! Data) {
            
        // !!! This is where I would like to update the EnvironmentObject userEnv !!!   
        // What is the best way to do this? Remember, this class has already been initialised within the ExtensionDelegate.
        }
    }
}
//ExtensionDelegate of Apple Watch app, initialising the WatchConnectivityProvider
class ExtensionDelegate: NSObject, WKExtensionDelegate {

    func applicationDidFinishLaunching() {
        // Perform any final initialization of your application.
        WatchConnectivityProvider.shared.activateSession()
    }
}

依賴注入

一種解決方案可能是全局存儲對@EnvironmentObject的引用,例如。 在一些依賴容器中。

enum Dependencies {
    struct Name: Equatable {
        let rawValue: String
        static let `default` = Name(rawValue: "__default__")
        static func == (lhs: Name, rhs: Name) -> Bool { lhs.rawValue == rhs.rawValue }
    }

    final class Container {
        private var dependencies: [(key: Dependencies.Name, value: Any)] = []

        static let `default` = Container()

        func register(_ dependency: Any, for key: Dependencies.Name = .default) {
            dependencies.append((key: key, value: dependency))
        }

        func resolve<T>(_ key: Dependencies.Name = .default) -> T {
            return (dependencies
                .filter { (dependencyTuple) -> Bool in
                    return dependencyTuple.key == key
                        && dependencyTuple.value is T
                }
                .first)?.value as! T
        }
    }
}

然后你像這樣創建你的 object:

Dependencies.Container.default.register(User())

您可以從代碼中的任何位置訪問它:

let user: User = Dependencies.Container.default.resolve()
user.modify()

Swift 的Dependency Injection的更詳細解釋可以在這里找到。

Singleton

或者,您可以使用標准Singleton模式使您的用戶數據在全球范圍內可用。 更詳細的解釋可以在這里找到。

最后的想法

SwiftUI 的干凈架構是一個很好的例子(至少在我看來)如何以干凈的方式編寫 iOS 應用程序。 這有點復雜,但你可以拿起一些部分。

這里糟糕的巨型代碼:

class ExtensionDelegate: ObservableObject, NSObject, WCSessionDelegate, WKExtensionDelegate {
var session: WCSession?
@Published var vm = ViewModel

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
    print(#function)
    var replyValues = Dictionary<String, Any>()
    replyValues["status"] = "failed"
    
    // 2442 Bytes
    if let data = message["data"] as? Data {
        // push that work back to the main thread
        DispatchQueue.main.async {
            self.vm = try? JSONDecoder().decode(ViewModel.self, from: data)
        }
        if let vm = vm {
            replyValues["status"] = "ok"
            replyValues["id"] = vm.id.uuidString
        }
    }
    replyHandler(replyValues)
}
...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM