View.environmentObject(_:) for 可能作为该视图的祖先而丢失

Posted

技术标签:

【中文标题】View.environmentObject(_:) for 可能作为该视图的祖先而丢失【英文标题】:A View.environmentObject(_:) for may be missing as an ancestor of this view 【发布时间】:2020-03-28 08:34:04 【问题描述】:

我刚刚更新到 Xcode 11.4,它破坏了我的代码。我将一些用户设置存储在 ObservableObject 中,如下所示:

class UserSettings: ObservableObject   
    @Published var cardOrder = UserDefaults.standard.integer(forKey: "Card Order")  
    @Published var cardTheme = UserDefaults.standard.integer(forKey: "Card Theme")  
    @Published var translation = UserDefaults.standard.integer(forKey: "Translation")  
    @Published var overdueFirst = UserDefaults.standard.bool(forKey: "Overdue First")  
    @Published var randomNum = 0  
  

这是我的主菜单,设置环境对象已成功传递到设置视图,我可以在其中保存和检索用户选择。

struct ContentView: View   
  @State var settings = UserSettings()  

  var body: some View   
    SubView().environmentObject(settings)  
    
  

struct SubView: View   

  @EnvironmentObject var settings: UserSettings  

  var body: some View   
    List   
      NavigationLink (destination: Flashcard())  
        HStack   
          Image(systemName: "rectangle.on.rectangle.angled")  
          Text(verbatim: "Study")      
          
        

      NavigationLink (destination: Settings())   
        HStack   
          Image(systemName: "gear")  
          Text(verbatim: "Settings")  
          
        
      
    
  

但在我的抽认卡视图中,我收到一个错误:致命错误:未找到 UserSettings 类型的 ObservableObject。 UserSettings 的 View.environmentObject(_:) 作为此视图的祖先可能会丢失。:文件 SwiftUI,第 0 行

错误出现在我启动 Frontside 的第 13 行。在原始代码中,我只是调用了 Frontside 子视图,但我想解决这个错误,我必须添加 .environmentObject(settings),但即使添加了它,我的应用程序也会编译,但一进入 Flashcard 视图就会崩溃。

struct Flashcard: View   
  @EnvironmentObject var settings: UserSettings  

  @State var colour = UserDefaults.standard.integer(forKey: "Card Theme") * 6  
  @State private var showResults: Bool = false  
  @State private var fullRotation: Bool = false  
  @State private var showNextCard: Bool = false  


  var body: some View   
    let zstack = ZStack   

      Frontside(id: $settings.randomNum, sheet: $showingSheet, rotate: $fullRotation, invis: $showNextCard, col: $colour).environmentObject(self.settings)  
      //   


      Backside(id: $settings.randomNum, sheet: $showingSheet, bookmark: $bookmarked, results: $showResults, rotate: $fullRotation, invis: $showNextCard, col: $colour, trans: $translation).environmentObject(self.settings)  
    //  

      
    

有谁知道我做错了什么?此代码在之前的 Xcode 中编译并运行良好。

【问题讨论】:

这里的问题完全相同。应用程序在升级到 13.4 之前正在修复:/ 不过,它在模拟器上运行良好。它只会在设备上崩溃。你也一样? 不,我的模拟器也崩溃了。该应用程序加载正常,但是当我转到此特定视图时,它崩溃了。但我不知道出了什么问题,因为我有其他使用该环境对象的子视图并且它们没有崩溃。 【参考方案1】:

我认为您也应该将settings 对象传递给FlashCardSettings。 试试这个:

struct ContentView: View   
  @State var settings = UserSettings()  

  var body: some View   
    SubView().environmentObject(settings)  
    
  

struct SubView: View   

  @EnvironmentObject var settings: UserSettings  

  var body: some View   
    List   
      NavigationLink (destination: Flashcard().environmentObject(settings))  
        HStack   
          Image(systemName: "rectangle.on.rectangle.angled")  
          Text(verbatim: "Study")      
          
        

      NavigationLink (destination: Settings().environmentObject(settings))   
        HStack   
          Image(systemName: "gear")  
          Text(verbatim: "Settings")  
          
        
      
    
  

【讨论】:

为什么这是必要的呢?传递给祖先视图(即“子视图”)的 environmentObject 不应该被后代视图(即闪存卡和设置)自动访问吗?与直接作为 Flashcard/Settings 视图的属性传递相比,这种方法给我们带来了什么好处?【参考方案2】:

@EnvironmentObject 必须直接填充 @StateObject@ObservedObjectObservableObject 而不是 @State

struct ContentView: View   
    //@ObservedObject
    @StateObject var settings = UserSettings()  

    var body: some View   
        SubView().environmentObject(settings)  
      
  

注意:UserSettings 必须是 ObservableObject

Apple documentation on managing model data

struct BookReader: App 
    @StateObject var library = Library()

    var body: some Scene 
        WindowGroup 
            LibraryView()
                .environmentObject(library)
        
    


struct LibraryView: View 
    @EnvironmentObject var library: Library

    // ...

【讨论】:

【参考方案3】:

我在模拟器中运行 ios 14.3,在我的情况下,错误是关于我的 environmentObject NavigationController。通过在SceneDelegate 中修改ContentView().environmentObject(NavigationController()) 解决了这个问题,如果您希望预览工作,也可以在ContentView_Previews 中进行。

【讨论】:

【参考方案4】:
import SwiftUI

@main

// there is a file with the name of your "projectApp" (JuegosSwiftUIApp in my case)

struct JuegosSwiftUIApp: App  
    var body: some Scene 
        WindowGroup 
            DatosIniciales() // any view
                .environmentObject(Datos()) // this solved it (Datos() is class type Observableobject) 
        
    

【讨论】:

虽然此代码可以回答问题,但提供有关 如何 和/或 为什么 解决问题的附加上下文将改善答案的长期价值。【参考方案5】:

去掉 let zstack =

ZStack   

      Frontside(id: $settings.randomNum, sheet: $showingSheet, rotate: $fullRotation, invis: $showNextCard, col: $colour).environmentObject(self.settings)  
      //   


      Backside(id: $settings.randomNum, sheet: $showingSheet, bookmark: $bookmarked, results: $showResults, rotate: $fullRotation, invis: $showNextCard, col: $colour, trans: $translation).environmentObject(self.settings)  
    //  

      

【讨论】:

以上是关于View.environmentObject(_:) for 可能作为该视图的祖先而丢失的主要内容,如果未能解决你的问题,请参考以下文章

英语高手请进

简易先进先出队列-自用

函数参数

多重背包

合租房合同模板

启动代码分析 02