@Published 是 Swift 和 SwiftUI 中一个与 Combine 框架 相关的属性包装器(Property Wrapper),主要用于标记某个属性的值变化需要被自动发布(Publish)。它通常与 ObservableObject 协议结合使用,用于构建响应式的数据模型,让 SwiftUI 视图能够监听数据变化并自动更新。
核心作用
-
自动发布变化
当一个属性被标记为@Published时,它的值发生变化会触发一个事件,通知所有订阅者(比如 SwiftUI 视图)。这使得视图能够自动更新。 -
与
ObservableObject配合
@Published必须用在遵循ObservableObject协议的类中。这样的类可以通过@ObservedObject或@StateObject被 SwiftUI 视图观察,从而实现数据驱动的 UI 更新。
示例代码
import Combine
// 1. 定义一个遵循 ObservableObject 协议的类
class User: ObservableObject {
// 2. 用 @Published 标记需要监听的属性
@Published var name: String = "John"
@Published var age: Int = 25
}
// 3. 在 SwiftUI 视图中使用
struct ProfileView: View {
// 4. 通过 @ObservedObject 或 @StateObject 观察 User 实例
@ObservedObject var user: User
var body: some View {
VStack {
Text("姓名: \(user.name)")
Text("年龄: \(user.age)")
Button("修改信息") {
// 5. 修改 @Published 属性时,视图会自动更新
user.name = "Alice"
user.age += 1
}
}
}
}
关键细节
-
仅适用于类
@Published只能用于类的属性(class),因为ObservableObject协议要求类型是引用类型(Reference Type)。 -
手动触发更新
如果某个属性的修改不需要触发视图更新,可以不用@Published。例如:class User: ObservableObject { @Published var name = "John" // 修改会触发更新 var internalId = UUID() // 修改不会触发更新 } -
底层实现
@Published本质上是通过 Combine 框架的CurrentValueSubject实现的。当属性值变化时,它会发出一个事件,通知所有订阅者。 -
与
@State的区别@State:用于视图内部私有状态,值类型(结构体或简单数据)。@Published:用于类的属性,配合ObservableObject实现跨视图的数据共享。
常见问题
为什么修改了 @Published 属性,但视图没有更新?
- 确保类遵循
ObservableObject。 - 确保在视图中使用
@ObservedObject或@StateObject包装类的实例。 - 确保属性修改发生在主线程(SwiftUI 的 UI 更新必须在主线程)。
能否在结构体(struct)中使用 @Published?
不能。@Published 依赖 ObservableObject,而该协议仅适用于类。
总结
@Published是构建响应式数据模型的关键工具,用于标记需要触发视图更新的属性。- 结合
ObservableObject协议和@ObservedObject/@StateObject,可以实现跨视图的数据共享和自动更新。 - 它是 SwiftUI 数据驱动 UI 的核心机制之一!