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

SwiftUI中@EnvironmentObject值变更时保留ViewModel值的方法

解决SwiftUI中子视图状态因父视图环境对象变更重置的问题

问题原因

你的ChildView是结构体类型,当valueComingFromParent(环境对象)的属性变更时,ChildView的body会触发重计算,结构体实例被重新创建。而你在ChildView内部直接初始化@ObservedObject var viewModel = ChildViewModel(),每次结构体重建都会生成新的ChildViewModel实例,导致counter被重置为初始值0。

解决方案

方案1:使用@StateObject替代@ObservedObject(iOS 14+)

@StateObject是SwiftUI专门用来在View生命周期内保留对象实例的属性包装器,即使View结构体重建,它持有的对象也不会被重新初始化。修改代码如下:

struct ChildView: View {
    // 替换@ObservedObject为@StateObject
    @StateObject var viewModel = ChildViewModel()
    @EnvironmentObject var valueComingFromParent: SomeOtherViewModel

    var body: some View {
        VStack {
            Button("Toast", action: {
                valueComingFromParent.toast.toggle()
            })
            Button("Incrementer \(viewModel.counter)", action: {
                viewModel.counter += 1
            })
        }
    }
}

方案2:从父视图传递ViewModel(兼容iOS 13)

如果需要兼容iOS 13,将ChildViewModel的实例创建权交给父视图,通过参数传递给子视图,这样子视图重建时不会重新创建ViewModel实例:

父视图代码:

struct ParentView: View {
    // 父视图持有ChildViewModel实例
    @StateObject var childViewModel = ChildViewModel()
    @StateObject var parentViewModel = SomeOtherViewModel()

    var body: some View {
        ChildView(viewModel: childViewModel)
            .environmentObject(parentViewModel)
    }
}

子视图修改后代码:

struct ChildView: View {
    // 通过参数接收父视图传递的ViewModel
    @ObservedObject var viewModel: ChildViewModel
    @EnvironmentObject var valueComingFromParent: SomeOtherViewModel

    var body: some View {
        VStack {
            Button("Toast", action: {
                valueComingFromParent.toast.toggle()
            })
            Button("Incrementer \(viewModel.counter)", action: {
                viewModel.counter += 1
            })
        }
    }
}

两种方案都能保证viewModel.counter在valueComingFromParent变更时保留当前值,你可以根据iOS版本需求选择合适的方案。

内容的提问来源于stack exchange,提问作者Nabeel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 21:01:21