关于SwiftUI中的@EnvironmentObject的困惑

时间:2019-11-21 07:22:39

标签: swiftui

我正在尝试在SwiftUI中练习@EnvironmentObject工具。
共享对象UserContentView中的初始化。
当我从ContentView切换到NameView时,效果很好。
但是,从NameView到AgeView失败。 (请查看错误消息和代码会话)

错误消息

Fatal error: No ObservableObject of type User found.

有人可以给我建议吗?我想念什么吗?

代码

init "User" type in contentView
NavigationView

+-----------+                   +--------+                   +-------+
|ContentView+--NavigationLink-->|NameView+--NavigationLink-->|AgeView|
+-----------+                   +--------+                   +-------+
final class User: ObservableObject {
    @Published var name: String
    @Published var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

struct ContentView: View {
    var user: User = User(name: "SomeName", age: 44)
    var body: some View {
        NavigationView {
            VStack {
                Text("name: \(self.user.name) age: \(self.user.age)")
                NavigationLink(destination: NameView().environmentObject(self.user)) {
                    Text("Show Name")
                }
            }
        }
    }
}

struct NameView: View {
    @EnvironmentObject var user: User
    var body: some View {
        VStack {
            Text("name: \(self.user.name)")
            NavigationLink(destination: AgeView()) {
                Text("Show Age")
            }
        }
    }
}

struct AgeView: View {
    @EnvironmentObject var user: User
    var body: some View {
        VStack {
            Text("age: \(self.user.age)")
        }
    }
}

2 个答案:

答案 0 :(得分:0)

您正在将SceneDelegate中的EnvironmentObject分配给ContentView,因此ContentView的所有子视图都可以自动访问您的User。

因此不必像下面这样再次传递:NameView().environmentObject(self.user)

如果在.sheet修饰符内显示一个View,则只需再次传递environmentObject,因为它基本上是一个新的独立视图。

final class User: ObservableObject {
    @Published var name: String
    @Published var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

struct ContentView: View {
    @EnvironmentObject var user: User
    var body: some View {
        NavigationView {
            VStack {
                Text("name: \(self.user.name) age: \(self.user.age)")
                NavigationLink(destination: NameView()) {
                    Text("Show Name")
                }
            }
        }
    }
}

struct NameView: View {
    @EnvironmentObject var user: User
    var body: some View {
        VStack {
            Text("name: \(self.user.name)")
            NavigationLink(destination: AgeView()) {
                Text("Show Age")
            }
        }
    }
}

struct AgeView: View {
    @EnvironmentObject var user: User
    var body: some View {
        VStack {
            Text("age: \(self.user.age)")
        }
    }
}

答案 1 :(得分:0)

希望以下示例对您有帮助:

我们的模型可以可观察,并且具有所有变量已发布

class A: ObservableObject {
    @Published var id: String = ""
    @Published var value: String = ""
}

当将其用作 EnvironmentObject 时,请确保已在 SceneDelegate.swift 中进行如下设置:

let example = Example()

    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: example.environmentObject(A()))
        self.window = window
        window.makeKeyAndVisible()
    }

然后我们可以在所有视图中使用此 EnvironmentObject

struct Example: View {

    @EnvironmentObject var obj: A

    var body: some View {
        Button(action: {
            self.obj.value = "Hi im changed"
        }) {
            Text("Change me")
        }
    }
}

有时候,当您想更新此对象中的数据时,xCode可能会为您提供有关'未为...类名等设置环境对象'的错误。,在这种情况下,您需要传递一个EnvironmentObject到目标视图:

DestinationView().environmentObject(self.A)

希望这会有所帮助,祝你好运!