let stringSub = PublishSubject()
let intSub = PublishSubject()
Observable.combineLatest(stringSub, intSub) { strElement, intElement in
"\(strElement) \(intElement)"
}.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
stringSub.onNext("L")
stringSub.onNext("G")
intSub.onNext(1)
intSub.onNext(2)
stringSub.onNext("dyz")
G 1
G 2
dyz 2
步骤1:Filter -> combinelatest -> CombineLatest+arity.swift 针对两个Observable(CombineLatest+Collection.swift集合 针对多个)
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
- seealso: [combineLatest operator on reactivex.io](http://reactivex.io/documentation/operators/combinelatest.html)
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
public static func combineLatest
(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.Element, O2.Element) throws -> Element)
-> Observable {
return CombineLatest2(
source1: source1.asObservable(), source2: source2.asObservable(),
resultSelector: resultSelector
)
}
}
步骤2:点击 CombineLatest2( )
2.1 self._source1 = source 保存stringSub.asObservable()
2.2 self.source2 = source2 保存intSub.asObservable()
2.3 self.resultSelector = resultSelector 保存闭包{ strElement, intElement in "(strElement) (intElement)" }
2.4 外界.subscribe 会来到下面的run方法
2.5 CombineLatestSink2(parent: self, observer: observer, cancel: cancel) 初始化自己CombineLatestSink2和父类CombineLatestSink
final class CombineLatest2 : Producer {
typealias ResultSelector = (E1, E2) throws -> Result
let _source1: Observable
let _source2: Observable
let _resultSelector: ResultSelector
init(source1: Observable, source2: Observable, resultSelector: @escaping ResultSelector) {
self._source1 = source1
self._source2 = source2
self._resultSelector = resultSelector
}
override func run(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Result {
let sink = CombineLatestSink2_(parent: self, observer: observer, cancel: cancel)
let subscription = sink.run()
return (sink: sink, subscription: subscription)
}
}
步骤3:点击 run
3.1 super.init(arity: 2, observer: observer, cancel: cancel) 初始化2.5中的父类CombineLatestSink
3.2 subscription1.setDisposable(self._parent._source1.subscribe(observer1)) -> subscribe 来到 父类CombineLatestSink的next方法 ???subscribe为什么来到next???
3.3 subscription1.setDisposable(self._parent._source1.subscribe(observer1)) -> subscribe 来到 父类CombineLatestSink的next方法
final class CombineLatestSink2_ : CombineLatestSink {
typealias Result = Observer.Element
typealias Parent = CombineLatest2
let _parent: Parent
var _latestElement1: E1! = nil
var _latestElement2: E2! = nil
init(parent: Parent, observer: Observer, cancel: Cancelable) {
self._parent = parent
super.init(arity: 2, observer: observer, cancel: cancel)
}
func run() -> Disposable {
let subscription1 = SingleAssignmentDisposable()
let subscription2 = SingleAssignmentDisposable()
let observer1 = CombineLatestObserver(lock: self._lock, parent: self, index: 0, setLatestValue: { (e: E1) -> Void in self._latestElement1 = e }, this: subscription1)
let observer2 = CombineLatestObserver(lock: self._lock, parent: self, index: 1, setLatestValue: { (e: E2) -> Void in self._latestElement2 = e }, this: subscription2)
subscription1.setDisposable(self._parent._source1.subscribe(observer1))
subscription2.setDisposable(self._parent._source2.subscribe(observer2))
return Disposables.create([
subscription1,
subscription2
])
}
override func getResult() throws-> Result {
return try self._parent._resultSelector(self._latestElement1, self._latestElement2)
}
}
步骤4:来到next方法
class CombineLatestSink
: Sink
, CombineLatestProtocol {
typealias Element = Observer.Element
let _lock = RecursiveLock()
private let _arity: Int
private var _numberOfValues = 0
private var _numberOfDone = 0
private var _hasValue: [Bool]
private var _isDone: [Bool]
init(arity: Int, observer: Observer, cancel: Cancelable) {
self._arity = arity
self._hasValue = [Bool](repeating: false, count: arity)
self._isDone = [Bool](repeating: false, count: arity)
super.init(observer: observer, cancel: cancel)
}
func getResult() throws -> Element {
rxAbstractMethod()
}
func next(_ index: Int) {
if !self._hasValue[index] {
self._hasValue[index] = true
self._numberOfValues += 1
}
if self._numberOfValues == self._arity {
do {
let result = try self.getResult()
self.forwardOn(.next(result))
}
catch let e {
self.forwardOn(.error(e))
self.dispose()
}
}
else {
var allOthersDone = true
for i in 0 ..< self._arity {
if i != index && !self._isDone[i] {
allOthersDone = false
break
}
}
if allOthersDone {
self.forwardOn(.completed)
self.dispose()
}
}
}
func fail(_ error: Swift.Error) {
self.forwardOn(.error(error))
self.dispose()
}
func done(_ index: Int) {
if self._isDone[index] {
return
}
self._isDone[index] = true
self._numberOfDone += 1
if self._numberOfDone == self._arity {
self.forwardOn(.completed)
self.dispose()
}
}
}