SwiftUI中的EnvironmentObject在View初始化器中不可用?

3

我成功地将environmentObject appSettings传递到了我的视图中。我可以使用它来修改视图中的字体和选择器。但是,如果我尝试在视图的init()函数中访问一个已发布的环境对象变量,它会崩溃并显示以下错误信息:

Thread 1: Fatal error: No ObservableObject of type AppSettings found.
A View.environmentObject(_:) for AppSettings may be missing as an ancestor of this view.

在自定义SwiftUI视图初始化程序中使用environmentObject是否有特殊规则?

以下是我的视图代码开头。环境对象是appSettings。如果我在初始化器中注释掉第2行并取消注释第3行,则应用程序可以正常工作。请注意,我稍后在Picker中成功使用“appSettings.interfaces”。

struct CaptureFilterView: View {

@State var etherCapture: EtherCapture? = nil
@EnvironmentObject var appSettings: AppSettings
@Binding var frames: [Frame]
@State var captureFilter: String = ""
@State var error: String = ""
@State var numberPackets = 10

@State var interface: String = ""
init(frames: Binding<[Frame]>) {
    self._frames = frames
    self.interface = appSettings.interfaces.first ?? "en0" //CRASH HERE
    //self.interface = "en0"  //uncomment this and comment line above to make app "work"
}
var body: some View {
    HStack() {
        ...
        Picker(selection: $interface, label: Text("")) {
            ForEach(appSettings.interfaces, id: \.self) { interfaceName in
                Text(interfaceName).tag(interfaceName)
            }
        }

以下是我在AppDelegate.swift中创建顶级内容视图的位置

        let contentView = ContentView(showCapture: true).environmentObject(appSettings)

为了确保,我在创建顶级 ContentView 中的 CaptureFilterView 时,也传递了 environmentObject。这不是必需的,也不会改变行为。

            if showCapture { CaptureFilterView(frames: self.$frames).environmentObject(appSettings) }

供参考,这是我的appSettings的顶部:

class AppSettings: ObservableObject {
    @Published var font: Font
    @Published var interfaces: [String]
1个回答

11

SwiftUI环境对象在View初始化程序中不可用?

是的,SwiftUI环境对象在View初始化程序中不可用。为什么?很简单-它是在对象初始化之后注入的。

让我们以上面的ContentView为例来考虑它是如何实现的:

let contentView = ContentView(showCapture: true).environmentObject(appSettings)

这里发生了什么?

  1. ContentView类型的实例化和初始化值
let newInstance = ContentView.init(showCapture: true) 
  1. newInstance注入的appSetting属性上调用函数func environmentObject()
let contentView = newInstance.environmentObject(appSettings)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接