SwiftUI @EnvironmentObject 错误:可能作为此视图的祖先丢失

Sky*_*Sky 12 xcode swift ios13 swiftui

我的第一个视图可以从 API 请求中获取所有数据,然后打开第二个视图更改 API 请求数据,它崩溃了。

下面是错误

Fatal error: No ObservableObject of type NetworkManager found.
A View.environmentObject(_:) for NetworkManager may be missing as an ancestor of this view.: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-39.3/Core/EnvironmentObject.swift, line 55
2019-11-07 12:00:01.961425-0800 EarthQuake[73703:5913116] Fatal error: No ObservableObject of type NetworkManager found.
A View.environmentObject(_:) for NetworkManager may be missing as an ancestor of this view.: file /BuildRoot/Library/Caches/com.apple.xbs/Sources/Monoceros_Sim/Monoceros-39.3/Core/EnvironmentObject.swift, line 55
Run Code Online (Sandbox Code Playgroud)

这是从 API 获取数据的 swift 文件,然后将数据保存到帖子

import Foundation
import Combine

final class NetworkManager: ObservableObject {

    @Published var posts = [Post]()


    func fetchData() {

         //some code to fetch data, then save to posts

    }

}
Run Code Online (Sandbox Code Playgroud)

在我的第一个列表视图文件中:EarthQuakeList.swift


import SwiftUI

struct EarthQuakeList: View {

    @EnvironmentObject var networkManager: NetworkManager

    //@ObservedObject var networkManager = NetworkManager()

    var body: some View {

        NavigationView {
            List(networkManager.posts) { post in
                NavigationLink(destination: EarthQuakeDetail(detail: post.properties, location: post.locationCoordinate)) {
                    ListRow(magnitude: post.properties.mag ?? 0.0, place: post.properties.place)

                }

            }
          .navigationBarTitle(Text("Today"))      
            .navigationBarItems(

                    trailing:
                    VStack {

                        Button(action: {
                            print("Edit button tapped")
                            self.showEditPage.toggle()
                        }) {
                            //Top right icon
                            Image(systemName: "pencil.circle")
                                .resizable()
                                .frame(width: 20, height: 20, alignment: .center)
                        }.sheet(isPresented: $showEditPage) { 
                            return EditPage().environmentObject(self.networkManager)

                        }

                    }




            )



        }
        .onAppear {
            //Call function to fetch data
            self.networkManager.fetchData()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

一切正常,我可以看到所有数据,但是当我在第二个视图文件中做同样的事情时,我取回了数据,但它没有为第一个视图更新

在我的第二个编辑视图文件中:EditPage.swift

import SwiftUI

struct EditPage: View {

    //@ObservedObject var networkManager = NetworkManager()

    @EnvironmentObject var networkManager: NetworkManager

    var body: some View {

        VStack {
            Text("Edite")


        }
        .onAppear(){

            //I called the same function to get data as in first view file, but it is not updating the list view 
            self.networkManager.fetchData()


        }

    }
}
Run Code Online (Sandbox Code Playgroud)

SceneDelegate.swift

import UIKit
import SwiftUI

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        //Set up environment object
        let contentView = EarthQuakeList().environmentObject(NetworkManager())

        // Use a UIHostingController as window root view controller.
        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            window.rootViewController = UIHostingController(
                rootView: contentView
            )
            self.window = window
            window.makeKeyAndVisible()
        }
    }
Run Code Online (Sandbox Code Playgroud)

所以我期待第二个视图文件调用函数self.networkManager.fetchData()从 API 调用中获取数据,然后更新第一个 swift 文件EarthQuakeList 中的列表视图,问题是我只是得到正确的数据,视图没有更新有新数据

Sky*_*Sky 37

整个问题很容易解决,只需添加 self.networkManager @ EarthQuakeList.swift

.sheet(isPresented: $showEditPage) { 
                            return EditPage().environmentObject(self.networkManager)
Run Code Online (Sandbox Code Playgroud)

我从文章中得到了原因和启发:https : //github.com/peterfriese/Swift-EnvironmentObject-Demo

  • 我正在使用此解决方案将环境对象添加到我的 .sheet 中。但是,在我的 .sheet 中,我有导航链接以进一步查看。看来我必须使用上述解决方案通过 NavigationLink 层次结构将环境对象传递到每个后续视图,否则我会遇到“无法观察到的对象”崩溃。我本以为父级 .sheet 的后续视图将是 .sheet 的子级,从而继承环境对象,但情况似乎并非如此。有人对此有什么想法吗? (2认同)