【问题标题】:SwiftUI EnvironmentObject not available in View initializer?SwiftUI EnvironmentObject 在 View 初始化程序中不可用?
【发布时间】:2020-06-16 06:14:53
【问题描述】:

我成功地将 environmentObject appSettings 传递到我的视图中。我可以使用它来修改我的字体和视图中的选择器。但是,如果我尝试在视图 init() 中访问 environmentObject 发布的变量,它会崩溃:

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 是否有特殊规则?

这是我的视图代码的开始。 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]

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    SwiftUI EnvironmentObject 在 View 初始化程序中不可用?

    是的,SwiftUI EnvironmentObject 在视图初始化程序中不可用。为什么?这很简单——它是在对象初始化之后注入的。

    让我们考虑一下上面ContentView的例子是如何完成的:

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

    那么这里发生了什么?这里

    1) ContentView 类型的值的实例化和初始化

    let newInstance = ContentView.init(showCapture: true) 
    

    2) 在newInstance 上调用函数func environmentObject() 注入appSetting 属性

    let contentView = newInstance.environmentObject(appSettings)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 2020-07-29
      • 1970-01-01
      • 2020-03-01
      • 2020-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多