简体   繁体   English

SwiftUI @EnvironmentObject 错误:可能缺少此视图的祖先

[英]SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view

my first view can get all the data from API request, then opened second view to change the API request data, it crashed.我的第一个视图可以从 API 请求中获取所有数据,然后打开第二个视图更改 API 请求数据,它崩溃了。

below is the error下面是错误

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

This is swift file to fetch data from API, then save data to posts这是 swift 文件,用于从 API 获取数据,然后将数据保存到帖子

import Foundation
import Combine

final class NetworkManager: ObservableObject {

    @Published var posts = [Post]()


    func fetchData() {

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

    }

}

In my first list view file: EarthQuakeList.swift在我的第一个列表视图文件中: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()
        }
    }
}

Everything works well, I can see all the data, but when I do the same thing in my second view file, I get the data back, but it does not update for the first view一切正常,我可以看到所有数据,但是当我在第二个视图文件中做同样的事情时,我得到了数据,但它不会为第一个视图更新

In my second editing view file: EditPage.swift在我的第二个编辑视图文件中: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()


        }

    }
}

SceneDelegate.swift 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()
        }
    }

So I am expecting second view file to call function self.networkManager.fetchData() to get data from API call, then update list view in first swift file EarthQuakeList , the issue is I am just getting correct data back, the view is not updating with new data So I am expecting second view file to call function self.networkManager.fetchData() to get data from API call, then update list view in first swift file EarthQuakeList , the issue is I am just getting correct data back, the view is not updating有新数据

The whole issue is very easy to fix just add self.networkManager @ EarthQuakeList.swift整个问题很容易解决,只需添加 self.networkManager @ EarthQuakeList.swift

.sheet(isPresented: $showEditPage) { 
                            return EditPage().environmentObject(self.networkManager)

I got the reason and inspired from article: https://github.com/peterfriese/Swift-EnvironmentObject-Demo我从文章中得到了原因和启发: https://github.com/peterfriese/Swift-EnvironmentObject-Demo

if you are using sheet ore navigation you have to pass the environment Object maybe its a bug of swiftUI but it works for me in Xcode 11.5:如果您使用的是片矿石导航,则必须通过环境 Object 可能是 swiftUI 的错误,但它在 Xcode 11 中对我有用。

.sheet(isPresented: $show){
        mySheetView().environmentObject(self.myEnviromentObject)
}

This problem seems to be cause by using two instances of NetworkManager in your code.此问题似乎是由于在您的代码中使用了两个NetworkManager实例造成的。

If you add this line to the NetworkManager :如果将此行添加到NetworkManager

final class NetworkManager: … {

    static let shared = NetworkManager()

}

And then update the references in your two views like this:然后像这样更新两个视图中的引用:

struct EarthQuakeList: … {

    @ObservedObject var networkManager = NetworkManager.shared

    …

}

struct EditPage: … {

    @ObservedObject var networkManager = NetworkManager.shared

    …

}

This will make sure both views use the exact same object to access the information.这将确保两个视图使用完全相同的 object 来访问信息。 By using the same object, updates in one view will cause the other view to be updated as well.通过使用相同的 object,一个视图中的更新将导致另一个视图也被更新。

Once this works, I recommend to play around with .environmentObject() ( example ) in SwiftUI as this would allow for sharing the same instance of these service types across your application.一旦这可行,我建议在 SwiftUI 中使用.environmentObject() ( example ),因为这将允许在您的应用程序中共享这些服务类型的相同实例。

Good luck with your project!祝你的项目好运!

I think may be you have used the keyword final to the class networkManager我想可能是您对 class networkManager 使用了关键字 final

Trying removing the keyword and try尝试删除关键字并尝试

暂无
暂无

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

相关问题 SwiftUI @EnvironmentObject 错误:可能缺少此视图的祖先——访问 init() 中的对象 - SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view -- accessing object in the init() 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