SwiftUI:必须将 ObservableObject 作为 EnvironmentObject 传递到 View 中吗?
SwiftUI: Must an ObservableObject be passed into a View as an EnvironmentObject?
如果我使用 @Published
属性 创建一个 ObservableObject
并使用 .environmentObject()
将其注入到 SwifUI 视图中,该视图会按预期响应 ObservableObject 中的更改.
class CounterStore: ObservableObject {
@Published private(set) var counter = 0
func increment() {
counter += 1
}
}
struct ContentView: View {
@EnvironmentObject var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
点击“增量”将增加计数。
但是,如果我不使用 EnvironmentObject
而是将存储实例传递到视图中,编译器不会报错,当点击按钮时会调用存储方法 increment()
,但 View
中的计数 不会 更新。
struct ContentViewWithStoreAsParameter: View {
var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter) (DOES NOT UPDATE)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
以下是我调用两个视图的方式:
@main
struct testApp: App {
var store = CounterStore()
var body: some Scene {
WindowGroup {
VStack {
ContentView().environmentObject(store) // works
ContentViewWithStoreAsParameter(store: store) // broken
}
}
}
}
有没有办法将 ObservableObject
作为参数传递到视图中? (或者 .environmentalObject()
在幕后施展了什么魔法?)
不知何故应该观察到,所以下一个作品
struct ContentViewWithStoreAsParameter: View {
@ObservedObject var store: CounterStore
//...
您可以轻松将您的店铺传承为 @StateObject
:
@main
struct testApp: App {
@StateObject var store = CounterStore()
var body: some Scene {
WindowGroup {
VStack {
ContentView().environmentObject(store) // works
ContentViewWithStoreAsParameter(store: store) // also works
}
}
}
}
struct ContentViewWithStoreAsParameter: View {
@StateObject var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter)") // now it does update
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
但是,商店通常只对需要它的视图可用,为什么这个解决方案在这种情况下最有意义:
struct ContentView: View {
@StateObject var store = CounterStore()
var body: some View {
VStack {
Text("Count: \(store.counter)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
如果我使用 @Published
属性 创建一个 ObservableObject
并使用 .environmentObject()
将其注入到 SwifUI 视图中,该视图会按预期响应 ObservableObject 中的更改.
class CounterStore: ObservableObject {
@Published private(set) var counter = 0
func increment() {
counter += 1
}
}
struct ContentView: View {
@EnvironmentObject var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
点击“增量”将增加计数。
但是,如果我不使用 EnvironmentObject
而是将存储实例传递到视图中,编译器不会报错,当点击按钮时会调用存储方法 increment()
,但 View
中的计数 不会 更新。
struct ContentViewWithStoreAsParameter: View {
var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter) (DOES NOT UPDATE)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
以下是我调用两个视图的方式:
@main
struct testApp: App {
var store = CounterStore()
var body: some Scene {
WindowGroup {
VStack {
ContentView().environmentObject(store) // works
ContentViewWithStoreAsParameter(store: store) // broken
}
}
}
}
有没有办法将 ObservableObject
作为参数传递到视图中? (或者 .environmentalObject()
在幕后施展了什么魔法?)
不知何故应该观察到,所以下一个作品
struct ContentViewWithStoreAsParameter: View {
@ObservedObject var store: CounterStore
//...
您可以轻松将您的店铺传承为 @StateObject
:
@main
struct testApp: App {
@StateObject var store = CounterStore()
var body: some Scene {
WindowGroup {
VStack {
ContentView().environmentObject(store) // works
ContentViewWithStoreAsParameter(store: store) // also works
}
}
}
}
struct ContentViewWithStoreAsParameter: View {
@StateObject var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter)") // now it does update
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
但是,商店通常只对需要它的视图可用,为什么这个解决方案在这种情况下最有意义:
struct ContentView: View {
@StateObject var store = CounterStore()
var body: some View {
VStack {
Text("Count: \(store.counter)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}