- 可连接的序列和一般序列不同在于:有订阅时不会立刻开始发送事件消息,只有当调用
connect()之后才会开始发送值。 - 可连接的序列可以让所有的订阅者订阅后,才开始发出事件消息,从而保证我们想要的所有订阅者都能接收到事件消息。
| 操作符 | 描述 |
|---|---|
| publish & connect | $1 |
| replay | $1 |
| multicast | $1 |
| refCount | $1 |
| share | $1 |
/// 延迟函数
func delay(_ delay: Double, closure: @escaping () -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
closure()
}
}
- 普通序列样式
let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
interval.subscribe(onNext: { print("订阅:1,事件:\($0)") })
.disposed(by: self.disposeBag)
delay(3) {
interval.subscribe(onNext: { print("订阅:2,事件:\($0)") })
.disposed(by: self.disposeBag)
}
delay(10) {
self.disposeBag = DisposeBag()
}
//输出:
订阅:1,事件:0
订阅:1,事件:1
订阅:1,事件:2
订阅:1,事件:3
订阅:2,事件:0
订阅:1,事件:4
订阅:2,事件:1
订阅:1,事件:5
订阅:2,事件:2
订阅:1,事件:6
订阅:2,事件:3
订阅:1,事件:7
订阅:2,事件:4
订阅:1,事件:8
订阅:2,事件:5
订阅:1,事件:9
发现有一个问题:在延时3s之后订阅的Subscription: 2的计数并没有和Subscription: 1一致,而是又从0开始了,如果想共享,怎么办?
-
publish & connect
1)publish: 将 Observable 转换为可被连接的 Observable
2)connect: 通知 ConnectableObservable 可以开始发出元素了
3)publish: 将源可观察序列转换为可连接序列 共享一个Observable的事件序列,避免创建多个Observable sequence。
4)注意:需要调用connect之后才会开始发送事件

let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).publish()
interval.subscribe(onNext: { print("订阅:1,事件:\($0)") })
.disposed(by: disposeBag)
delay(2) {
_ = interval.connect()
}
delay(4) {
interval.subscribe(onNext: { print("订阅:2,事件:\($0)") }).disposed(by: self.disposeBag)
}
delay(6) {
interval.subscribe(onNext: { print("订阅:3, 事件: \($0)") })
.disposed(by: self.disposeBag)
}
delay(10) {
self.disposeBag = DisposeBag()
}
输出:
订阅:1,事件:0
订阅:1,事件:1
订阅:2,事件:1
订阅:1,事件:2
订阅:2,事件:2
订阅:1,事件:3
订阅:2,事件:3
订阅:3, 事件: 3
订阅:1,事件:4
订阅:2,事件:4
订阅:3, 事件: 4
订阅:1,事件:5
订阅:2,事件:5
订阅:3, 事件: 5
订阅:1,事件:6
订阅:2,事件:6
订阅:3, 事件: 6
-
replay
1)将源可观察序列转换为可连接的序列,并将向每个新订阅服务器重放以前排放的缓冲大小
2)首先拥有和publish一样的能力,共享 Observable sequence, 其次使用replay还需要我们传入一个参数(buffer size)来缓存已发送的事件,当有新的订阅者订阅了,会把缓存的事件发送给新的订阅者

let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).replay(5)
interval.subscribe(onNext: { print(Date.time, "订阅:1,事件:\($0)")}).disposed(by: disposeBag)
delay(2) { _ = interval.connect() }
delay(4) {
interval.subscribe(onNext: { print(Date.time,"订阅:2,事件:\($0)") })
.disposed(by: self.disposeBag)
}
delay(8) {
interval.subscribe(onNext: { print(Date.time,"订阅: 3, 事件: \($0)") })
.disposed(by: self.disposeBag)
}
delay(10, closure: {
self.disposeBag = DisposeBag()
})
//输出:
2019-10-25 19-12-25 订阅:1,事件:0
2019-10-25 19-12-26 订阅:2,事件:0
2019-10-25 19-12-26 订阅:1,事件:1
2019-10-25 19-12-26 订阅:2,事件:1
2019-10-25 19-12-27 订阅:1,事件:2
2019-10-25 19-12-27 订阅:2,事件:2
2019-10-25 19-12-28 订阅:1,事件:3
2019-10-25 19-12-28 订阅:2,事件:3
2019-10-25 19-12-29 订阅:1,事件:4
2019-10-25 19-12-29 订阅:2,事件:4
2019-10-25 19-12-30 订阅: 3, 事件: 0
2019-10-25 19-12-30 订阅: 3, 事件: 1
2019-10-25 19-12-30 订阅: 3, 事件: 2
2019-10-25 19-12-30 订阅: 3, 事件: 3
2019-10-25 19-12-30 订阅: 3, 事件: 4
2019-10-25 19-12-30 订阅:1,事件:5
2019-10-25 19-12-30 订阅:2,事件:5
2019-10-25 19-12-30 订阅: 3, 事件: 5
2019-10-25 19-12-31 订阅:1,事件:6
2019-10-25 19-12-31 订阅:2,事件:6
2019-10-25 19-12-31 订阅: 3, 事件: 6
-
multicast
将源可观察序列转换为可连接序列,并通过指定的主题广播其发射。
let netOB = Observable<Any>.create { (observer) -> Disposable in
sleep(2)//模拟网络延迟
print("我开始请求网络了")
observer.onNext("请求到的网络数据")
observer.onNext("请求到的本地")
observer.onCompleted()
return Disposables.create {
print("销毁回调了")
}
}.publish()
netOB.subscribe(onNext: { (anything) in
print("订阅1:",anything)
})
.disposed(by: disposeBag)
// 我们有时候不止一次网络订阅,因为有时候我们的数据可能用在不同的额地方
// 所以在订阅一次 会出现什么问题?
netOB.subscribe(onNext: { (anything) in
print("订阅2:",anything)
})
.disposed(by: disposeBag)
_ = netOB.connect()
输出:
我开始请求网络了
订阅1: 请求到的网络数据
订阅2: 请求到的网络数据
订阅1: 请求到的本地
订阅2: 请求到的本地
销毁回调了
-
refCount
1)操作符将自动连接和断开可被连接的 Observable
2)它将可被连接的 Observable 转换为普通 Observable。当第一个观察者对它订阅时,那么底层的 Observable 将被连接。当最后一个观察者离开时,那么底层的 Observable 将被断开连接

//每隔1秒钟发送1个事件
let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.publish()
.refCount()
//第一个订阅者(立刻开始订阅)
_ = interval
.subscribe(onNext: { print("订阅1: \($0)") })
.disposed(by: disposeBag)
//第二个订阅者(延迟5秒开始订阅)
delay(5) {
_ = interval
.subscribe(onNext: { print("订阅2: \($0)") })
.disposed(by: self.disposeBag)
}
delay(10, closure: {
self.disposeBag = DisposeBag()
})
//输出:
订阅1: 0
订阅1: 1
订阅1: 2
订阅1: 3
订阅1: 4
订阅1: 5
订阅2: 5
订阅1: 6
订阅2: 6
订阅1: 7
订阅2: 7
订阅1: 8
订阅2: 8
订阅1: 9
订阅2: 9
-
share(relay:)
1)该操作符将使得观察者共享源 Observable,并且缓存最新的 n 个元素,将这些元素直接发送给新的观察者。
2)简单来说 shareReplay 就是 replay 和 refCount 的组合。 示例:
//每隔1秒钟发送1个事件
let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
.share(replay: 5)
//第一个订阅者(立刻开始订阅)
_ = interval
.subscribe(onNext: { print("订阅1: \($0)") })
.disposed(by: disposeBag)
//第二个订阅者(延迟5秒开始订阅)
delay(5) {
_ = interval
.subscribe(onNext: { print("订阅2: \($0)") })
.disposed(by: self.disposeBag)
}
delay(10, closure: {
self.disposeBag = DisposeBag()
})
输出:
订阅1: 0
订阅1: 1
订阅1: 2
订阅1: 3
订阅1: 4
订阅2: 0
订阅2: 1
订阅2: 2
订阅2: 3
订阅2: 4
订阅1: 5
订阅2: 5
订阅1: 6
订阅2: 6
订阅1: 7
订阅2: 7
订阅1: 8
订阅2: 8
订阅1: 9
订阅2: 9