在 watchOS 中使用 environmentObject
Posted
技术标签:
【中文标题】在 watchOS 中使用 environmentObject【英文标题】:Using environmentObject in watchOS 【发布时间】:2019-06-12 06:15:00 【问题描述】:我正在尝试在 watchOS6 应用中使用 environmentObject
将我的数据模型绑定到我的视图。
我在 Xcode 11 中创建了一个简单的独立 Watch 应用。
我创建了一个新的DataModel
类
import Combine
import Foundation
import SwiftUI
final class DataModel: BindableObject
let didChange = PassthroughSubject<DataModel,Never>()
var aString: String = ""
didSet
didChange.send(self)
在我的ContentView
结构中,我使用@EnvironmentObject
绑定这个类 -
struct ContentView : View
@EnvironmentObject private var dataModel: DataModel
var body: some View
Text($dataModel.aString.value)
最后,我尝试将DataModel
的实例注入到HostingController
类中的环境中-
class HostingController : WKHostingController<ContentView>
override var body: ContentView
return ContentView().environmentObject(DataModel())
但是,我得到一个错误:
Cannot convert return expression of type '_ModifiedContent<ContentView, _EnvironmentKeyWritingModifier<DataModel?>>' to return type 'ContentView'
错误是因为WKHostingController
是一个需要具体类型的泛型——在这种情况下为WKHostingController<ContentView>
。
类似的方法在 ios 应用中与 UIHostingController
完美配合,因为 UIHostingController
不是泛型类。
还有其他方法可以将环境注入到 watchOS 视图中吗?
【问题讨论】:
这能回答你的问题吗? How to inject .environmentObject() in watchOS6 【参考方案1】:您可以使用类型擦除,AnyView
在 SwiftUI 的情况下为 View
。
我会重构 WKHostingController
以返回 AnyView
。
这对我来说似乎编译得很好。
class HostingController : WKHostingController<AnyView>
override var body: AnyView
return AnyView(ContentView().environmentObject(DataModel()))
【讨论】:
谢谢。我试过AnyView
,但我没有用过AnyView(ContentView())
这对我不起作用,我收到以下错误:“'AnyView' 类型的属性'body' 无法覆盖'ContentView' 类型的属性”
几个月后才回到这个问题上,新鲜的眼睛会有所帮助。我在通用协议声明中仍然有 ContentView,更改为 AnyView 并且可以工作。
如何让子 ContentView 在最新的 WatchOS 应用程序模板中访问它?我在我的主要 ContentView 上工作,但是当我使用 NavigationLink
路由到视图时,我无法弄清楚 ContentView 如何访问相同的 @EnvironmentObject
这是一个糟糕的答案,因为AnyView
性能很重。长话短说,将您的数据模型放在内容视图中。 Here's better solution【参考方案2】:
对于像 Brett(在 cmets 中)这样的人来说,
"Property 'body' with type 'AnyView' cannot override a property with type 'ContentView'"
我得到了同样的错误,因为我没有替换返回值并包装了正在返回的 ContentView。
即。这是我第一次尝试的样子..注意
WKHostingController<ContentView>
那应该是
WKHostingController<AnyView>
class HostingController : WKHostingController<ContentView>
override var body: AnyView
return AnyView(ContentView().environmentObject(DataModel()))
【讨论】:
虽然我已经做了那一点,但我没有用 AnyView 替换 WKHostingController添加到 Matteo 的精彩答案,
如果你想使用委托,那么这样使用:
class HostingController : WKHostingController<AnyView>
override var body: AnyView
var contentView = ContentView()
contentView.environmentObject(DataModel())
contentView.delegate = self
let contentWrapperView = AnyView(contentView)
return contentWrapperView
【讨论】:
以上是关于在 watchOS 中使用 environmentObject的主要内容,如果未能解决你的问题,请参考以下文章
watchOS 3 在设备和手表之间共享的类中使用 WCSession
WatchOS 在条件视图中使用 ObservableObject 导致运行时错误