SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view
SwiftUI @EnvironmentObject error: may be missing as an ancestor of this view
我的第一个视图可以从 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()
}
}
}
一切正常,我可以看到所有数据,但是当我在我的第二个视图文件中做同样的事情时,我得到了数据,但它不会为第一个视图更新
在我的第二次编辑视图文件中: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 调用中获取数据,然后首先更新列表视图 swift 文件 EarthQuakeList,问题是我只是得到正确的数据,视图没有更新新数据
这个问题似乎是由于在您的代码中使用了两个 NetworkManager
实例引起的。
如果将此行添加到 NetworkManager
:
final class NetworkManager: … {
static let shared = NetworkManager()
}
然后像这样更新两个视图中的引用:
struct EarthQuakeList: … {
@ObservedObject var networkManager = NetworkManager.shared
…
}
struct EditPage: … {
@ObservedObject var networkManager = NetworkManager.shared
…
}
这将确保两个视图使用完全相同的对象来访问信息。通过使用相同的对象,一个视图中的更新将导致另一个视图也被更新。
一旦成功,我建议在 SwiftUI 中使用 .environmentObject()
(example),因为这将允许在您的应用程序中共享这些服务类型的相同实例。
祝你项目顺利!
整个问题很容易解决,只需添加 self.networkManager @ EarthQuakeList.swift
.sheet(isPresented: $showEditPage) {
return EditPage().environmentObject(self.networkManager)
我从文章中得到了原因和启发:
https://github.com/peterfriese/Swift-EnvironmentObject-Demo
如果你正在使用 sheet 矿石导航,你必须传递环境对象,这可能是 swiftUI 的一个错误,但它适用于 Xcode 11.5:
.sheet(isPresented: $show){
mySheetView().environmentObject(self.myEnviromentObject)
}
我的第一个视图可以从 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()
}
}
}
一切正常,我可以看到所有数据,但是当我在我的第二个视图文件中做同样的事情时,我得到了数据,但它不会为第一个视图更新
在我的第二次编辑视图文件中: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 调用中获取数据,然后首先更新列表视图 swift 文件 EarthQuakeList,问题是我只是得到正确的数据,视图没有更新新数据
这个问题似乎是由于在您的代码中使用了两个 NetworkManager
实例引起的。
如果将此行添加到 NetworkManager
:
final class NetworkManager: … {
static let shared = NetworkManager()
}
然后像这样更新两个视图中的引用:
struct EarthQuakeList: … {
@ObservedObject var networkManager = NetworkManager.shared
…
}
struct EditPage: … {
@ObservedObject var networkManager = NetworkManager.shared
…
}
这将确保两个视图使用完全相同的对象来访问信息。通过使用相同的对象,一个视图中的更新将导致另一个视图也被更新。
一旦成功,我建议在 SwiftUI 中使用 .environmentObject()
(example),因为这将允许在您的应用程序中共享这些服务类型的相同实例。
祝你项目顺利!
整个问题很容易解决,只需添加 self.networkManager @ EarthQuakeList.swift
.sheet(isPresented: $showEditPage) {
return EditPage().environmentObject(self.networkManager)
我从文章中得到了原因和启发: https://github.com/peterfriese/Swift-EnvironmentObject-Demo
如果你正在使用 sheet 矿石导航,你必须传递环境对象,这可能是 swiftUI 的一个错误,但它适用于 Xcode 11.5:
.sheet(isPresented: $show){
mySheetView().environmentObject(self.myEnviromentObject)
}