[英]Trouble passing data between views using EnvironmentObject in SwiftUI
[英]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.