SwiftUI调用结构体变量时出现No ObservableObject类型错误求助
问题分析与解决方案
错误核心原因
你遇到的No ObservableObject of type StatsNavigationManager found错误,本质是环境对象的注入逻辑完全搞反了:
@EnvironmentObject的作用是从父视图的环境中读取已注入的ObservableObject实例,而不是在当前视图内部声明后再自己注入。- 你在
StatsView里用@EnvironmentObject声明statNavManager,又在自己的NavigationView上添加.environmentObject(self.statNavManager),此时self.statNavManager还未从环境中获取到实例,相当于注入了一个空对象,自然会触发错误。
正确解决方案步骤
1. 在父视图中创建并注入环境对象
必须在包含StatsView的上层父视图(比如App入口、TabView页面)中创建StatsNavigationManager实例,再通过.environmentObject()注入到环境中。
示例(App入口):
@main struct CrimeTrackingApp: App { // 用@StateObject持有ObservableObject实例,确保生命周期与App一致 @StateObject private var statNavManager = StatsNavigationManager() var body: some Scene { WindowGroup { TabView { StatsView() .tabItem { Label("Stats", systemImage: "chart.bar") } // 在这里注入环境对象 .environmentObject(statNavManager) // 其他标签页... } } } }
2. 修改StatsView代码
移除StatsView内部的.environmentObject(self.statNavManager)代码,保留@EnvironmentObject声明即可:
final class StatsNavigationManager: ObservableObject { @Published var screen: Screens? { didSet { print("📱 \(String(describing: screen))") } } func push(to screen: Screens) { self.screen = screen } func popToRoot() { self.screen = nil } } struct StatsView: View { let test = cityClass() struct Input{ var zip: String = "" } @State private var input: Input = .init() @FocusState private var inputFocused: Bool // 保留@EnvironmentObject声明,从父视图环境中获取实例 @EnvironmentObject var statNavManager: StatsNavigationManager var body: some View { NavigationView { ZStack { Color.blue VStack { inputTxtVw submitBtn } .toolbar { ToolbarItemGroup(placement: .keyboard) { Spacer() Text("Search") Button("Retrieve Data") { statNavManager.push(to: .statsPage) } .background( NavigationLink(destination: CityView(), tag: .statsPage, selection: $statNavManager.screen) { EmptyView() } ) } } .onSubmit(of: .text, submit) } } // 移除这里的.environmentObject(self.statNavManager) } // 补充你未贴出的视图组件实现 private var inputTxtVw: some View { TextField("Enter ZIP", text: $input.zip) .focused($inputFocused) .padding() .background(Color.white) .cornerRadius(8) } private var submitBtn: some View { Button("Submit") { submit() } .padding() .background(Color.white) .cornerRadius(8) } private func submit() { // 这里添加你的提交逻辑 statNavManager.push(to: .statsPage) } }
关键注意点
@StateObject:用于在父视图中持有ObservableObject实例,确保其生命周期与父视图绑定,避免重复创建。- 环境对象的注入层级:必须在目标视图的上层祖先视图上注入,目标视图通过
@EnvironmentObject读取,不能在视图内部自我注入。 - 如果你用的是SwiftUI 3.0以下版本,父视图中改用
@ObservedObject代替@StateObject即可。
内容的提问来源于stack exchange,提问作者Linda Xue
相关产品推荐
相关产品推荐

