在App文件中使用StateObject时出现ObservableObject致命错误
问题排查与解决办法
核心问题出在两个地方,导致你碰到Fatal error: No ObservableObject of type ExerciseManager found这个报错:
1. 视图渲染错误打断了EnvironmentObject的传递
在TodaysWorkoutView的列表行里,你直接把Sets、Reps、Rest这些Int类型的值传给Text组件,但SwiftUI的Text根本不支持直接接收非字符串类型的参数——这会导致视图渲染失败,间接触发了EnvironmentObject找不到的错误(因为视图初始化流程被中断了)。
2. 已弃用的NavigationView(次要但建议修正)
你代码里用的NavigationView在iOS 16之后已经被NavigationStack替代,虽然这不是直接报错的原因,但可能导致视图层级出现异常,建议一起换掉。
具体修复步骤
第一步:修正TodaysWorkoutView的Text类型错误
把Int类型的属性转成字符串再传给Text,同时替换NavigationView为NavigationStack:
import SwiftUI struct TodaysWorkoutView: View { @EnvironmentObject var dataManager: ExerciseManager var body: some View { NavigationStack { // 替换成iOS16+支持的NavigationStack List(dataManager.movements, id: \.id) { exercise in HStack{ Text(exercise.ExerciseName) Text("\(exercise.Sets)") // Int转String Text("\(exercise.Reps)") // Int转String Text("\(exercise.Rest)") // Int转String } } .navigationTitle("今日训练") // 可选:加个导航标题,体验更好 } } } #Preview { NavigationStack{ TodaysWorkoutView() .environmentObject(ExerciseManager()) } }
第二步:确认EnvironmentObject的传递链路
你的GetFit App入口已经正确把dataManager注入到ContentView了,而TodaysWorkoutView是ContentView下TabView的子视图,理论上能自动继承到EnvironmentObject。只要修复了上面的视图渲染错误,这个报错应该就会消失。
第三步:可选:给ContentView的Preview补全EnvironmentObject
如果想正常预览ContentView,得给它的Preview注入所有需要的EnvironmentObject:
#Preview { ContentView() .environmentObject(AuthViewModel()) .environmentObject(TimerData()) .environmentObject(ExerciseManager()) }
额外验证点
- 检查Firestore里的
MyMovement集合字段名,要和代码里的id、ExerciseName、Sets等完全一致(大小写敏感)。 - 可以在
ExerciseManager的fetchExercises方法里加个打印语句,确认是否能正常获取数据:
func fetchExercises() { movements.removeAll() let db = Firestore.firestore() let ref = db.collection("MyMovement") ref.getDocuments{ snapshot, error in guard error == nil else { print(error!.localizedDescription) return } if let snapshot = snapshot { print("拿到了\(snapshot.documents.count)条训练数据") // 加这句验证 for document in snapshot.documents { let data = document.data() let id = data["id"] as? String ?? "" let ExerciseName = data["ExerciseName"] as? String ?? "" let Sets = data["Sets"] as? Int ?? 3 let Reps = data["Reps"] as? Int ?? 10 let Rest = data["Rest"] as? Int ?? 45 let exercise = Movement(id: id, ExerciseName: ExerciseName, Sets: Sets, Reps: Reps, Rest: Rest) self.movements.append(exercise) } } } }
内容的提问来源于stack exchange,提问作者Zevzy
相关产品推荐
相关产品推荐

