SwiftUI中@EnvironmentObject结合Picker触发致命错误,请求排查
@EnvironmentObject结合Picker崩溃问题的修复方案
问题根源
- 多实例数据源冲突:PickerView内部通过
@StateObject创建了独立的DataExample实例,同时又将该实例注入环境;但当它被嵌套进PickerResultView时,PickerResultView自身持有另一个DataExample实例(通过@EnvironmentObject获取),导致出现两个完全独立的数据源,数据流无法同步,还会触发依赖注入相关的致命错误。 - 冗余的环境对象注入:
PickerResultView中的Text额外添加.environmentObject(data)属于冗余操作,不仅无意义,还可能造成逻辑混淆。
修复代码
1. 修改PickerView(移除内部数据源,改为接收外部环境对象)
import SwiftUI @MainActor class DataExample : ObservableObject { @Published var testnumber = "Test" } struct PickerView: View { // 改为通过@EnvironmentObject接收外部传入的数据源 @EnvironmentObject var data: DataExample var body: some View { VStack { Picker( selection: $data.testnumber, label: Text("PickerName"), content: { Text("John").tag("John") .foregroundColor(.black) Text("Freddy").tag("Freddy") .foregroundColor(.black) Text("Becky").tag("Becky") .foregroundColor(.black) }) .frame(width: 120, height: 45) .pickerStyle(.wheel) } // 无需在此注入环境对象,data已从外部获取 } } struct PickerView_Previews: PreviewProvider { static var previews: some View { PickerView() .environmentObject(DataExample()) // 预览时必须注入数据源 } }
2. 修改PickerResultView(移除冗余注入,共享同一数据源)
import SwiftUI struct PickerResultView: View { @EnvironmentObject var data: DataExample var body: some View { HStack { PickerView() // 自动继承当前环境中的data实例 Text("\(data.testnumber)") } } } struct PickerResultView_Previews: PreviewProvider { static var previews: some View { PickerResultView() .environmentObject(DataExample()) } }
3. 根视图注入数据源(关键步骤)
在App的根结构体中注入唯一的DataExample实例,确保整个视图树共享同一数据源:
@main struct YourApp: App { @StateObject private var data = DataExample() var body: some Scene { WindowGroup { PickerResultView() .environmentObject(data) } } }
修复说明
- 整个视图层级共享同一个
DataExample实例,Picker的选择操作会实时同步到data.testnumber,Text组件也能实时显示最新值。 - 彻底避免了多数据源实例导致的逻辑混乱,同时确保
@EnvironmentObject在所有需要的视图中被正确注入,不会触发致命错误。
内容的提问来源于stack exchange,提问作者alancord
相关产品推荐
相关产品推荐

