问题
I am trying to use environmentObject
in a watchOS6 app to bind my data model to my view.
I have created a simple, stand-alone Watch app in Xcode 11.
I created a new DataModel
class
import Combine
import Foundation
import SwiftUI
final class DataModel: BindableObject {
let didChange = PassthroughSubject<DataModel,Never>()
var aString: String = "" {
didSet {
didChange.send(self)
}
}
}
In my ContentView
struct I bind this class using @EnvironmentObject
-
struct ContentView : View {
@EnvironmentObject private var dataModel: DataModel
var body: some View {
Text($dataModel.aString.value)
}
}
Finally, I attempt to inject an instance of the DataModel
into the environment in the HostingController
class -
class HostingController : WKHostingController<ContentView> {
override var body: ContentView {
return ContentView().environmentObject(DataModel())
}
}
But, I get an error:
Cannot convert return expression of type '_ModifiedContent<ContentView, _EnvironmentKeyWritingModifier<DataModel?>>' to return type 'ContentView'
The error is because the WKHostingController
is a generic that needs a concrete type - WKHostingController<ContentView>
in this case.
A similar approach works perfectly with UIHostingController
in an iOS app because UIHostingController
isn't a generic class.
Is there some other way to inject the environment to a watchOS view?
回答1:
You can use type erasure, AnyView
in the case of SwiftUI View
.
I would refactor WKHostingController
to return AnyView
.
This seems to compile fine on my end.
class HostingController : WKHostingController<AnyView> {
override var body: AnyView {
return AnyView(ContentView().environmentObject(DataModel()))
}
}
回答2:
For anyone like Brett (in the comments) who was getting
"Property 'body' with type 'AnyView' cannot override a property with type 'ContentView'"
I got the same error because I hadn't replaced the return value and wrapped the ContentView being returned.
ie. this is what my first attempt looked like.. notice the
WKHostingController<ContentView>
that should be
WKHostingController<AnyView>
class HostingController : WKHostingController<ContentView> {
override var body: AnyView {
return AnyView(ContentView().environmentObject(DataModel()))
}
}
来源:https://stackoverflow.com/questions/56555709/using-environmentobject-in-watchos