Subject
- 观察者,继承于
Publisher
,作为一个观察者的身份,可以监听其他源 - 被观察者,可以发送数据流,提供给
Publisher
观察数据变化 - 可以实现自定义的数据源,内置实现了几个实例类
核心代码
public protocol Subject: AnyObject, Publisher {
//发布数据流,Output是Publisher的输入源类型
func send(_ value: Output)
//数据流完成的触发方式
func send(completion: Subscribers.Completion<Failure>)
// 发送一个订阅对象
func send(subscription: Subscription)
}
主要实现类
- CurrentValueSubject
- 会存储send或者init存的流数据,不会丢失
- 数据流如果触发了完成,后续再发送不会在收到数据流
- PassthroughSubject
- 首次不需要给初始值
- 数据流如果触发了完成,后续再发送不会在收到数据流
- PublishedSubject
- @Published 注解内部实现类
代码演示
-
CurrentValueSubject 演示流程
let current = CurrentValueSubject<Int, Never>(1) current.send(2) /// `CurrentValueSubject` 会记录最后一次send的值,当订阅时候,会及时 发出去,相当于热源 current.send(3) /// 订阅 current.sink { debugPrint("current \($0)") }.store(in: &cancel) current.send(4) /// 发布完成以后,订阅不会接收后续的数据流了 current.send(completion: .finished) current.send(5) /// 控制台输出: "current 3" "current 4" ```
-
PassthroughSubject
演示
let pass = PassthroughSubject<String, Never>()/// Pass /// `PassthroughSubject` 不会记录数据,相当于冷源,订阅后发出的数据流才会收到 pass.send("hello") /// 订阅 pass.sink { debugPrint("pass \($0)") }.store(in: &cancel) pass.send("world") /// 发布完成,后续发送的数据流 不会再被订阅接收 pass.send(completion: .finished) pass.send("over") /// 控制台输出 "pass world"
PublishedSubject
内置注解类, 和CurrentSubject
实现方式类似,但是不能发送完成事件
/// 回收类,页面释放需要调用cancel
lazy var cancel: [AnyCancellable] = []
/// 注解类 @Publish内置是一个@propertywrapper 包装了PublishedSubject
@Published var temperature: Double = 0
override func viewDidLoad() {
super.viewDidLoad()
self.temperature = 1
self.$temperature.sink { value in
debugPrint("value is : \(value)")
}.store(in: &cancel)
self.temperature = 2
self.temperature = 3
}
/// 控制器打印
"value is : 1.0"
"value is : 2.0"
"value is : 3.0"
```