iOS中的@Published是什么?

690 阅读2分钟

@Published 是 Swift 和 SwiftUI 中一个与 Combine 框架 相关的属性包装器(Property Wrapper),主要用于标记某个属性的值变化需要被自动发布(Publish)。它通常与 ObservableObject 协议结合使用,用于构建响应式的数据模型,让 SwiftUI 视图能够监听数据变化并自动更新。


核心作用

  1. 自动发布变化
    当一个属性被标记为 @Published 时,它的值发生变化会触发一个事件,通知所有订阅者(比如 SwiftUI 视图)。这使得视图能够自动更新。

  2. 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
            }
        }
    }
}

关键细节

  1. 仅适用于类
    @Published 只能用于类的属性(class),因为 ObservableObject 协议要求类型是引用类型(Reference Type)。

  2. 手动触发更新
    如果某个属性的修改不需要触发视图更新,可以不用 @Published。例如:

    class User: ObservableObject {
        @Published var name = "John"  // 修改会触发更新
        var internalId = UUID()       // 修改不会触发更新
    }
    
  3. 底层实现
    @Published 本质上是通过 Combine 框架的 CurrentValueSubject 实现的。当属性值变化时,它会发出一个事件,通知所有订阅者。

  4. @State 的区别

    • @State:用于视图内部私有状态,值类型(结构体或简单数据)。
    • @Published:用于类的属性,配合 ObservableObject 实现跨视图的数据共享。

常见问题

为什么修改了 @Published 属性,但视图没有更新?

  • 确保类遵循 ObservableObject
  • 确保在视图中使用 @ObservedObject@StateObject 包装类的实例。
  • 确保属性修改发生在主线程(SwiftUI 的 UI 更新必须在主线程)。

能否在结构体(struct)中使用 @Published

不能。@Published 依赖 ObservableObject,而该协议仅适用于类。


总结

  • @Published 是构建响应式数据模型的关键工具,用于标记需要触发视图更新的属性。
  • 结合 ObservableObject 协议和 @ObservedObject/@StateObject,可以实现跨视图的数据共享和自动更新。
  • 它是 SwiftUI 数据驱动 UI 的核心机制之一!