SwiftUI @EnvironmentObject error: может отсутствовать как предок этого представления - PullRequest
0 голосов
/ 07 ноября 2019

мое первое представление может получить все данные из запроса 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

Этофайл 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

    }

}

В моем первом файле просмотра списка: 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()
        }
    }
}

Все работает хорошо, Я вижу все данные, но когда я делаю то же самое во втором файле представления, я получаю данные обратно, но они не обновляются для первого представления

Во втором представлении редактированияfile: 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

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()
        }
    }

Поэтому я ожидаю, что файл второго вида вызовет функцию self. networkManager.fetchData () для получения данных из вызова API, затем обновите представление списка в первом быстром файле EarthQuakeList , проблема в том, что я просто получаю правильные данные обратно, представление не обновляется новыми данными

Ответы [ 2 ]

2 голосов
/ 08 ноября 2019

Весь вопрос очень легко исправить, просто добавьте self.networkManager @ EarthQuakeList.swift

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

Я получил причину и вдохновился статьей: https://github.com/peterfriese/Swift-EnvironmentObject-Demo

0 голосов
/ 07 ноября 2019

Эта проблема, по-видимому, вызвана использованием двух экземпляров NetworkManager в вашем коде.

Если вы добавите эту строку в NetworkManager:

final class NetworkManager: … {

    static let shared = NetworkManager()

}

, а затем обновитессылки в ваших двух представлениях выглядят так:

struct EarthQuakeList: … {

    @ObservedObject var networkManager = NetworkManager.shared

    …

}

struct EditPage: … {

    @ObservedObject var networkManager = NetworkManager.shared

    …

}

Это обеспечит, чтобы оба представления использовали один и тот же объект для доступа к информации. Используя тот же объект, обновления в одном представлении приведут к обновлению и другого представления.

Как только это сработает, я рекомендую поэкспериментировать с .environmentObject() ( пример ) вSwiftUI позволяет использовать один и тот же экземпляр этих типов служб в вашем приложении.

Удачи в вашем проекте!

...