如何使用SwiftUI EnvironmentObject

vmjh9lq9  于 2023-10-15  发布在  Swift
关注(0)|答案(2)|浏览(139)

根据苹果官方指南,我猜如果每个视图只有一个环境对象,那么这样做就可以了。当有多个对象时,我不确定对象是如何被引用的。

struct LandmarkList: View {
    @EnvironmentObject private var userData: UserData
...
 ForEach(userData.landmarks) { landmark in
                    if !self.userData.showFavoritesOnly || landmark.isFavorite {
                        NavigationLink(
                            destination: LandmarkDetail(landmark: landmark)
                                .environmentObject(self.userData)

                        ) {
                            LandmarkRow(landmark: landmark)
                        }
                    }
                }

上面是苹果官方指南中的代码,在LandMarkDetail文件中

struct LandmarkDetail: View {
    @EnvironmentObject var userData: UserData

我想知道LandMarkList中的environmentObject如何引用LandmarkDetail中的environment对象。他们被束缚了吗?我在文件中添加了第二个EnvironmentObject,但什么也没有发生

struct LandmarkDetail: View {
    @EnvironmentObject var userData: UserData
    @EnvironmentObject var testData: UserData

那么如何引用每个userData和testData呢?
编辑:我尝试在以下文件中添加环境对象:

import SwiftUI

struct LandmarkList: View {
    @EnvironmentObject private var userData: UserData
    @EnvironmentObject private var testData: TestData
    var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $userData.showFavoritesOnly) {
                    Text("Show Favorites Only")
                }
                Toggle(isOn: $testData.testbool) {
                                   Text("Test")
                }
...
struct LandmarksList_Previews: PreviewProvider {
    static var previews: some View {
        ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
            LandmarkList()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
        .environmentObject(UserData())
        .environmentObject(TestData())
    }
}
final class TestData: ObservableObject {
    @Published var testbool = false
}

预览崩溃了。Xcode可以编译,但立即给出以下错误

Fatal error: No ObservableObject of type TestData found.
A View.environmentObject(_:) for TestData may be missing as an ancestor of this view.: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-30.4/Core/EnvironmentObject.swift, line 55
2019-10-12 19:07:46.565707+0800 Landmarks[13034:643289] Fatal error: No ObservableObject of type TestData found.
A View.environmentObject(_:) for TestData may be missing as an ancestor of this view.: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-30.4/Core/EnvironmentObject.swift, line 55
j2cgzkjk

j2cgzkjk1#

别忘了在Scenedelegate中这样做来绑定你的对象:

window.rootViewController = UIHostingController(rootView: contentView.environmentObject(TestData()).environmentObject(UserData()))
wdebmtf2

wdebmtf22#

请了解如何在swiftUI中使用环境对象。我的解释与这里的一般编码规范有点一致。
我认为apple在环境对象上尝试的是创建一个单例类。你只需要创建一次,就可以在任何地方使用它。但是因为swiftUI是声明式的,所以在swiftUI中每个类都是按自上而下的顺序创建的,你不能自由地传递数据。你受到了很大的限制。
如何在swiftUI中使用单例类(环境对象)。
这些是步骤:
1.创建一个你想在任何地方访问的类的示例,并将其注入到代码的顶层(记住自顶向下),这样每个子视图都可以访问它。

struct Demo: App {
    var demoController = demoController()
    var body: some Scene {
        WindowGroup {
            ContentView()
            .environmentObject(demoController)
        }
    }
    }

1.然后使用@EnvironmentObject访问该单个示例,在任何您想要的视图中。

struct someOtherView: View {
    @EnvironmentObject var demoController: demoController
    var body: some View {
       }
    }

1.最后,你要创建一个示例的类,应该符合@ObservableObject,并为你想要从不同视图修改的成员变量声明@Published。

class demoController : ObservableObject {
    @Published var someMember:Bool = false
    }

为了更好的解释(如果你有时间的话),请查看肖恩艾伦的视频-https://www.youtube.com/watch?v=b1oC7sLIgpI&ab_channel=SeanAllen,然后转到时间11:27:53
你的代码也会编译,但现在仍然会崩溃,这与预览有关。因此,就像步骤1一样,在预览中进行更改以避免崩溃。(将var设置为static,以便在静态函数中使用)

struct someOtherView_Previews: PreviewProvider {
    
    static var demoController = demoController()
    
    static var previews: some View {
        DrawingView()
        .environmentObject(demoController)
    }
}

相关问题