简体   繁体   English

SwiftUI @EnvironmentObject 错误:可能缺少此视图的祖先——访问 init() 中的对象

[英]SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view -- accessing object in the init()

The following code produces the runtime error: @EnvironmentObject error: may be missing as an ancestor of this view.以下代码产生运行时错误:@EnvironmentObject 错误:可能作为此视图的祖先丢失。 The tState in the environment is an @ObservedObject.环境中的 tState 是一个 @ObservedObject。

struct TEditorView: View {
    @EnvironmentObject private var tState: TState
    
    @State var name = ""
    
    init() {
        self._name = State(initialValue: tState.name)
    }
 
    var body: some View {
        ...
    }
}

XCode 12.0.1 iOS 14 XCode 12.0.1 iOS 14

The answer is that an Environment Object apparently cannot be accessed in an init() function.答案是环境对象显然不能在 init() 函数中访问。 However, an ObservedObject can be.但是,一个 ObservedObject 可以。 So I changed the code to this and it works.所以我把代码改成了这个,它可以工作。 To make it easy I turned TState into a singleton that I could access anywhere.为了方便起见,我将 TState 变成了一个可以在任何地方访问的单例。 This could probably replace the use of @EnvironmentObject in many situations.在许多情况下,这可能会取代 @EnvironmentObject 的使用。

struct TEditorView: View {
    @ObservedObject private var tState = TState.shared
    //@EnvironmentObject private var tState: TState
    
    @State var name = ""
    
    init() {
        self._name = State(initialValue: tState.name)
    }
 
    var body: some View {
        ...
    }
}

A different approach here could be to inject the initial TState value in the constructor and do-away with the @EnvironmentObject completely.这里的另一种方法可能是在构造函数中注入初始TState值并完全取消@EnvironmentObject Then from the parent view you can use the @EnvironmentObject value when creating the view.然后从父视图中,您可以在创建视图时使用@EnvironmentObject值。

struct TEditorView: View {
    @State var name = ""
    
    init(tState: TState) {
        self._name = State(initialValue: tState.name)
    }
 
    var body: some View {
        ...
    }
}

struct ContentView: View {
    @EnvironmentObject private var tState: TState
    
    var body: some View {
        TEditorView(state: tState)
    }
}

Or use a @Binding instead of @State if the name value is meant to be two-way.或者,如果name值是@State则使用@Binding而不是@State

In general I'd also question why you need the @EnvironmentObject in the constructor.一般来说,我还会质疑为什么在构造函数中需要@EnvironmentObject The idea is with a @EnvironmentObject is that it's represented the same in all views, so you should only need it body . @EnvironmentObject的想法是它在所有视图中表示相同,因此您应该只需要它body

If you need any data transformations it should be done in the object model itself, not the view.如果您需要任何数据转换,它应该在对象模型本身中完成,而不是在视图中。

The @State should be set as private and per the documentation should only be accessed in the View body . @State应该设置为private并且根据文档只能在View body访问。

https://developer.apple.com/documentation/swiftui/state https://developer.apple.com/documentation/swiftui/state

An @EnvironmentObject should be set using the ContentView().environmentObject( YourObservableObject )一个@EnvironmentObject应使用设置ContentView().environmentObject( YourObservableObject )

https://developer.apple.com/documentation/combine/observableobject https://developer.apple.com/documentation/swiftui/stateobject https://developer.apple.com/documentation/combine/observableobject https://developer.apple.com/documentation/swiftui/stateobject

Below is some Sample code下面是一些示例代码

import SwiftUI
class SampleOO: ObservableObject {
    @Published var name: String = "init name"
}
//ParentView
struct OOSample: View {
    //The first version of an @EnvironmentObject is an @ObservedObject or @StateObject
    //https://developer.apple.com/tutorials/swiftui/handling-user-input
    @ObservedObject var sampleOO: SampleOO = SampleOO()
    var body: some View {
        VStack{
            Button("change-name", action: {
                self.sampleOO.name = "OOSample"
            })
        
        Text("OOSample = " + sampleOO.name)
        //Doing this should fix your error code with no other workarounds
        ChildEO().environmentObject(sampleOO)
        SimpleChild(name: sampleOO.name)
        }
    }
}
//Can Display and Change name
struct ChildEO: View {
    @EnvironmentObject var sampleOO: SampleOO
    var body: some View {
        VStack{
            //Can change name
            Button("ChildEO change-name", action: {
                self.sampleOO.name = "ChildEO"
            })
            Text("ChildEO = " + sampleOO.name)
        }
    }
}
//Can only display name
struct SimpleChild: View {
    var name: String
    var body: some View {
        VStack{
            //Cannot change name
            Button("SimpleChild - change-name", action: {
                print("Can't change name")
                //self.name = "SimpleChild"
            })
            Text("SimpleChild = " + name)
        }
    }
}

struct OOSample_Previews: PreviewProvider {
    static var previews: some View {
        OOSample()
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SwiftUI @EnvironmentObject 错误:可能缺少此视图的祖先 - SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view SwiftUI A View.environmentObject(_:) for 可能作为此视图的祖先丢失。:文件 - SwiftUI A View.environmentObject(_:) for may be missing as an ancestor of this view.: file SwiftUI 致命错误:找不到类型为“”的 ObservableObject 和 @EnvironmentObject 错误:可能作为此视图的祖先丢失 - SwiftUI Fatal error: No ObservableObject of type " " found and @EnvironmentObject error: may be missing as an ancestor of this view AppInformation 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失 - A View.environmentObject(_:) for AppInformation may be missing as an ancestor of this view View.environmentObject(_:) 作为该视图的祖先可能会丢失——但并非总是如此…… - A View.environmentObject(_:) may be missing as an ancestor of this view - but not always… 找不到 CarouselViewModel 类型的 ObservableObject。 CarouselViewModel 的 View.environmentObject(_:) 作为该视图的祖先可能会丢失 - No ObservableObject of type CarouselViewModel found. A View.environmentObject(_:) for CarouselViewModel may be missing as an ancestor of this view SwiftUI View 协议中的 EnvironmentObject - EnvironmentObject in protocol of SwiftUI View SwiftUI @EnvironmentObject 在嵌套视图中共享 - SwiftUI @EnvironmentObject shared in nested view SwiftUI 视图未更新为 EnvironmentObject 更改 - SwiftUI view is not updating to EnvironmentObject change SwiftUI EnvironmentObject 与 View 不同步 - SwiftUI EnvironmentObject out of sync with View
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM