与Publisher 相对应,是观察者模式中的Observer,Publisher在自身状态改变时,调用Subscriber 的三个不同方法receive(subscription)
、 receive(_:Input)
、 receive(completion:)
来通知Subscriber
Subscriber 订阅Publisher 後会返回一个遵循
Cancellable
协定的AnyCancellable
,作用上类似於其他响应式框架中的dispose
,控制者订阅者的释放,在开发中可以将其作为属性栏位,在页面销毁时,调用AnyCancellable
内部的cancel()
方法进行资源释放
以下举一些常见的Subscriber 例子:
sink
Sink
是非常通用的Subscriber
,我们可以自由的处理数据流的状态,Publisher 还提供了extension func
:sink(receiveCompletion:, receiveValue:)
方法来直接订阅,为订阅者连结基於闭包的行为
let integers = (0...3)
integers.publisher
.sink { print("Received \($0)") }
参数:
receiveComplete
: 在完成时执行的闭包receiveValue
: 在收到值时执行的闭包let integers = (0...3)
integers.publisher
.sink(receiveCompletion:{print("Completion: \($0)")},
receiveValue:{ print("Value: \($0)")})
Subject
Subject 是一种 Publisher,你可以调用其 send(_:)
方法将值注入到数据流中,很适合将已有的程序改造成兼容 Combine,有些时候我们想随时在Publisher 插入值来通知订阅者,在Rx 中也提供了一个Subject
类型来实现。Subject 通常是一个中间代理,即可以作为Publisher,也可以作为Observer
subscribe(_:Subject)
方法订阅某个PublisherSubject
的两个send
方法,我们可以在数据流中随时插入数据目前在Combine 中,有三个已经实现对Subject
: AnySubject
,CurrentValueSubject
和PassthroughSubject
范例:
// Before
class ContentManager {
var content: [String] {
didSet {
delegate?.contentDidChange(content)
}
}
func getContent() {
content = ["hello", "world"]
}
}
// After
class ContentController {
var content = CurrentValueSubject<[String], NSError>([])
func getContent() {
content.value = ["hello", "world"]
}
}
CurrentValueSubject
的功能很简单,就是包含一个初始值,并且会在每次值变化的时候发送一个消息,这个值会被保存,可以很方便的用来替代Property Observer。在上例中,以前需要实现delegate 来获取变化,现在只需要订阅content 的变化即可,并且它作为一个Publisher,可以很方便的利用操作符进行组合变换
PassthroughSubject
和CurrentValueSubject
几乎一样,只是没有初始值,也不会保存任何值
Assign
Assign
可以很方便地将接收到的值通过KeyPath
设置到指定的Class 上(不支持Struct
),很适合将已有的程序改造成Reactive,将来自Publisher 的每个元素分配给物件中的属性
参数:
keyPath
:表示要分配属性的 keyPath。关於 Key-Path 表达式请参考此官方文章
object
:包含此属性的物件。订阅者在每次接收到新值时都会分配给该物件的属性class Student {
let name: String
var score: Int
init(name: String, score: Int) {
self.name = name
self.score = score
}
}
let student = Student(name: "Ryder", score: 91)
print(student.score)
let observer = Subscribers.Assign(object: student, keyPath: \Student.score)
let publisher = PassthroughSubject<Int, Never>()
publisher.subscribe(observer)
publisher.send(95)
print(student.score)
publisher.send(98)
print(student.score)
一旦publisher 的值发生改变,对应的student
的score
也会被更新
>>: javascript(event&DOM)(DAY18)
本篇大纲:tooltips 基础设定、tooltips 进阶应用 今天我们要来讲解算是D3最轻松简...
本篇来实际建立游戏场景! 建立游戏场景 建立游戏场景组件 game-scene.vue,并提供「跳跃...
在 SMTP Mail 之後,今天要跟大家介绍第二种通知方式 Custom alertscripts...
T0814 Denial of Service 攻击者为了破坏设备的功能,使用阻断服务的攻击,会在短...
首先,理论上今天应该进展使用Python到写资料进mySql,但是我发现用来记录log的套件像是lo...