SwiftUI自定义类实例注入异常:多实例变为同一实例求助
问题原因
@EnvironmentObject 是通过类型来匹配注入对象的,你注入了三个同类型的 WorkSpace 实例,SwiftUI 只会返回第一个被注入的实例(也就是 doctor),所以 lawyer 和 carseller 变量实际指向的都是 doctor 的实例,导致所有 Toggle 都显示 Doctor 的信息。
解决方案
方案1:用子类区分类型
给每个职业创建 WorkSpace 的子类,让每个类型唯一,这样 @EnvironmentObject 就能正确匹配对应实例。
修改 WorkSpace 类及子类
class WorkSpace: ObservableObject { var title: String var income: Int init(title: String, income: Int) { self.title = title self.income = income } } class DoctorWorkSpace: WorkSpace { init() { super.init(title: "Doctor", income: 60000) } } class LawyerWorkSpace: WorkSpace { init() { super.init(title: "Lawyer", income: 50000) } } class CarSellerWorkSpace: WorkSpace { init() { super.init(title: "Car Seller", income: 30000) } }
修改 App 结构体
@main struct LifeSimulationApp: App { @StateObject var doctor = DoctorWorkSpace() @StateObject var lawyer = LawyerWorkSpace() @StateObject var carseller = CarSellerWorkSpace() @StateObject var player = MainPlayer() var body: some Scene { WindowGroup { ContentView() .environmentObject(doctor) .environmentObject(lawyer) .environmentObject(carseller) .environmentObject(player) } } }
修改 OccupationView
struct OccupationView: View { @EnvironmentObject var doctor: DoctorWorkSpace @EnvironmentObject var lawyer: LawyerWorkSpace @EnvironmentObject var carseller: CarSellerWorkSpace @EnvironmentObject var player: MainPlayer // body 部分保持不变 }
修改预览代码
struct OccupationView_Previews: PreviewProvider { static var previews: some View { OccupationView() .environmentObject(MainPlayer()) .environmentObject(DoctorWorkSpace()) .environmentObject(LawyerWorkSpace()) .environmentObject(CarSellerWorkSpace()) } }
方案2:使用单一容器对象(推荐)
创建一个包含所有职业的 ObservableObject 容器,只注入这个容器,避免多个同类型环境对象的冲突,结构更简洁。
创建职业容器类
class OccupationsStore: ObservableObject { let doctor = WorkSpace(title: "Doctor", income: 60000) let lawyer = WorkSpace(title: "Lawyer", income: 50000) let carseller = WorkSpace(title: "Car Seller", income: 30000) }
修改 App 结构体
@main struct LifeSimulationApp: App { @StateObject var occupations = OccupationsStore() @StateObject var player = MainPlayer() var body: some Scene { WindowGroup { ContentView() .environmentObject(occupations) .environmentObject(player) } } }
修改 OccupationView
struct OccupationView: View { @EnvironmentObject var occupations: OccupationsStore @EnvironmentObject var player: MainPlayer var body: some View { NavigationView { Form { // 原 HStack 部分保持不变 Section { Toggle("\(occupations.doctor.title) (\(occupations.doctor.income)€)", isOn: $player.isDoctorOn) Toggle("\(occupations.lawyer.title) (\(occupations.lawyer.income)€)", isOn: $player.isLawyerOn) Toggle("\(occupations.carseller.title) (\(occupations.carseller.income)€)", isOn: $player.isCarsellerOn) } } .navigationTitle(player.name) } } }
修改预览代码
struct OccupationView_Previews: PreviewProvider { static var previews: some View { OccupationView() .environmentObject(MainPlayer()) .environmentObject(OccupationsStore()) } }
内容的提问来源于stack exchange,提问作者KatMood
相关产品推荐
相关产品推荐

