【问题标题】:SwiftUI Fatal error: No ObservableObject of type AppData found. A View.environmentObject(_:) for AppData may be missing as an ancestor of this viewSwiftUI 致命错误:未找到 AppData 类型的 ObservableObject。 AppData 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失
【发布时间】:2021-03-30 09:14:39
【问题描述】:

我运行代码,然后收到以下错误消息: 致命错误:未找到 AppData 类型的 ObservableObject。 AppData 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失。 我用谷歌搜索它以获得帮助,但找不到任何有用的建议.. 所以我在这里用代码询问(只显示与问题相关的行):

  1. AppData 文件
struct Shortcut {
    var title: String
    var option: String
}

struct ShortcutViewModel: Identifiable {
    var id = UUID()
    var shortcut: Shortcut
    
    var title: String {
        return shortcut.title.capitalized
    }
    
    var option: String {
        return shortcut.option
    }
}

class AppData: ObservableObject {
    @Published var userData: [ShortcutViewModel]
    
    @Published var showTitle: String {
        didSet {
            UserDefaults.standard.set(showTitle, forKey: "TitleInput")
        }
    }
    
    @Published var showOption: String {
        didSet {
            UserDefaults.standard.set(showOption, forKey: "OptionInput")
        }
    }
    
    init() {
        userData = [
            ShortcutViewModel(shortcut: Shortcut(title: "What for Dinner?", option: "Chinese")),
            ShortcutViewModel(shortcut: Shortcut(title: "What for Lunch?", option: "Pasta")),
            ShortcutViewModel(shortcut: Shortcut(title: "What for Breakfast?", option: "Toast"))
        ]
        self.showTitle = UserDefaults.standard.string(forKey: "TitleInput")!
        self.showOption = UserDefaults.standard.string(forKey: "OptionInput")!
    }
}
  1. 内容视图文件
struct ContentView: View {
    // MARK: - PROPERTY
    let createpage = CreateView()
    // MARK: - BODY
    var body: some View {
        ZStack {
            VStack {
                NavigationBarView()
                NavigationView{
                    ScrollView{
                        HStack {
                            NavigationLink("+ create a shortcut", destination: CreateView())
                                .font(.title3)
                                .foregroundColor(.blue)
                                .padding()
                                .frame(width: 200, height: 60)
                                .background(
                                RoundedRectangle(cornerRadius: 10,
                                                 style: .continuous)
                                    .fill(
                                        Color(red:0.2, green: 0.45, blue: 1.0, opacity: 0.3)))
                                    
                            Spacer()
                        } //: HStack - link to create page
                        //.frame(minWidth: 0, maxWidth: .infinity, maxHeight: 120)
                        .padding()
                    } //: ScrollView
                    
                    .navigationTitle("All Shortcuts")
                    
                } //: NavigationView
            
            } //: VStack
            .ignoresSafeArea(.all, edges: .all)
        } //: ZStack
        .ignoresSafeArea(.all, edges: .top)
    } //: var Body
}



// MARK: - PREVIEW
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(text: .constant(""))
        
    }
}
  1. 创建视图
struct CreateView: View {
    // MARK: - PROPERTY
    @Environment(\.presentationMode) var presentationMode
    @EnvironmentObject var appData: AppData
    @State var titleInput2 = ""
    @State var optionInput2 = ""
    
    // MARK: - BODY
    var body: some View {
        ZStack {
            VStack {
                NavigationView{
                    ScrollView{
                        HStack {
                            TextField("what is the title?", text: $titleInput2)
                                .font(.title2)
                                .foregroundColor(.white)
                                .padding()
                                .frame(width: 320, height: 80)
                                .background(
                                    RoundedRectangle(
                                        cornerRadius: 20,
                                        style: .continuous)
                                        .fill(
                                            Color(red:0.2, green: 0.45, blue: 1.0, opacity: 0.3)))
                                .padding()
                        } //: HStack - Textfield - title
                        .padding()
                        
                        HStack (spacing: 10) {
                            TextField("options", text: $optionInput2)
                                .font(.body)
                                .foregroundColor(.white)
                                .padding()
                                .frame(width: 120, height: 60, alignment: .leading)
                                .background(
                                    RoundedRectangle(
                                        cornerRadius: 10,
                                        style: .continuous)
                                        .fill(
                                            Color(red: 1.0, green: 0.2, blue: 0.2, opacity: 0.3)))
                                .padding()
                        } //: HStack - Textfield - option
                        .padding()
                        
                        Button(action: {
                            self.appData.showTitle = titleInput2 // *here I get fatal error msg*
                            self.appData.showOption = optionInput2
                            presentationMode.wrappedValue.dismiss()
                        }, label: {
                            Text("Save")
                                .padding()
                                .background(
                                    Circle()
                                        .fill(
                                            Color(red: 0.25, green: 0.1, blue: 0.6, opacity: 0.25))
                                        .frame(width: 120, height: 120))
                                
                        }) //: Button - save
                        .padding(.top, 150)
                    } //: Scroll View
                    .navigationTitle("Create a Shortcut")
                }//: Navigation View
            } //: VStack
            .ignoresSafeArea(.all, edges: .all)
        } //: ZStack
        .ignoresSafeArea(.all, edges: .all)
    } //: Body
}

struct CreateView_Previews: PreviewProvider {
    static var previews: some View {
        CreateView().environmentObject(AppData())
    }
}
  1. 应用文件
@main  // *here I get Fatal Error msg*
struct WFT_demo2App: App {
    var body: some Scene {
        WindowGroup {
            ContentView(text: .constant(""))
        }
    }
}

所以当我运行代码时,我在 CreateView 和主应用程序文件中看到了致命错误消息,我在上面标记了。 我查找了参考资料,但它们都使用旧版本的 Xcode 以及我的工作区中没有的应用程序委托和场景委托,我无法将它们真正应用到我的案例中。 我非常坚持使用 UserDefaults...

【问题讨论】:

    标签: swiftui


    【解决方案1】:

    EnvironmentObjects 必须由祖先视图提供!

      @main  
    struct WFT_demo2App: App {
        var body: some Scene {
            WindowGroup {
    
                ContentView(text: .constant(""))
                 .environmentObject(AppData())            // <<: Here!
    
            }
        }
    }
    

    【讨论】:

    • 非常感谢!这就是我的想法,但不知道该怎么说......我还有一个快速的问题,因为我现在遇到了一个新错误......你看到'self.showTitle = UserDefaults.standard'这一行有什么问题吗?字符串(forKey:“标题输入”)! ' 和 1. AppData 文件中的下一行?因为我在那里得到“线程 1:致命错误:在展开可选值时意外发现 nil”错误..
    • @PatrickLee:是的,我一开始就注意到了但是回答了您提出的问题,在 StackOverFlow 中,我们正在尝试回答和解决每个问题的一个问题,请提出新问题并在那里解释您的问题,我来新职位帮忙,但现在我想我们已经完成了。
    • 没错,谢谢!我会提出一个新问题:)
    猜你喜欢
    • 1970-01-01
    • 2020-05-11
    • 2021-12-30
    • 2021-05-22
    • 2021-06-24
    • 2021-07-08
    • 2020-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多