You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 00:56:04