SwiftUI中何时使用@State初始化@Observable对象?
结论:不要在@Observable类中使用@State
首先明确:@State是SwiftUI视图(View结构体)专用的属性包装器,绝对不能用在自定义的@Observable类里,你的第一种写法是错误的,编译或运行时都会出现不符合预期的问题。
两种写法的问题分析
带@State的写法:
@State的设计初衷是让SwiftUI接管视图内部状态的存储和生命周期,它只能依附于View结构体。把它用在@Observable类中完全不符合其设计逻辑,不仅不会实现你想要的共享效果,还可能导致状态管理混乱。不带@State的写法:
这种写法本身是合法的,但如果你的需求是共享TaskRepository实例(比如多个ViewModel或视图共用同一个仓库数据),直接在CardViewModel里初始化TaskRepository()会导致每个CardViewModel实例都拥有独立的仓库,达不到共享目的。正确的做法是通过依赖注入,在创建CardViewModel时传入已有的TaskRepository实例:@Observable class CardViewModel{ private let taskRepository: TaskRepository var title: String = "Name" // 通过初始化方法注入仓库 init(taskRepository: TaskRepository) { self.taskRepository = taskRepository } // 视图模型处理逻辑... }这样多个ViewModel就能共用同一个仓库实例,数据变化时所有关联的视图都会响应更新。
@State的正确适用场景
- 仅用于SwiftUI View结构体内部:用来存储视图私有的、不需要跨视图共享的状态,比如开关的选中状态、输入框的临时文本、分页的当前页码等。
- 管理值类型或轻量引用类型:比如
Bool、String、Int等值类型,或者不需要跨视图传递的简单引用类型(比如本地的临时数据模型)。 - 由SwiftUI托管生命周期:@State标记的状态会在视图重建时被SwiftUI保留,不会因为视图刷新而重置。
如果需要共享数据,推荐用这些方式:
- 用
@StateObject在View中创建全局/页面级的共享实例,再通过.environmentObject()注入环境,其他视图用@EnvironmentObject获取。 - 通过依赖注入的方式,在初始化ViewModel或View时直接传递共享实例(耦合度更低,便于测试)。
内容的提问来源于stack exchange,提问作者dev_dev
相关产品推荐
相关产品推荐

