我的第一个视图可以从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
这是一个快速文件,用于从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调用中获取数据,然后更新第一个快捷文件 EarthQuakeList 中的列表视图,问题是我只是返回正确的数据,视图未使用新数据更新
答案 0 :(得分:4)
整个问题很容易解决,只需添加self.networkManager @ EarthQuakeList.swift
.sheet(isPresented: $showEditPage) {
return EditPage().environmentObject(self.networkManager)
我有原因,并从文章中得到启发: https://github.com/peterfriese/Swift-EnvironmentObject-Demo
答案 1 :(得分:3)
如果使用片矿导航,则必须通过环境Object可能是swiftUI的错误,但它在Xcode 11.5中对我有用:
.sheet(isPresented: $show){
mySheetView().environmentObject(self.myEnviromentObject)
}
答案 2 :(得分:0)
此问题似乎是由于在代码中使用两个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),因为这样可以在您的应用程序中共享这些服务类型的相同实例。
祝您的项目好运!