Swift框架學習之-RxSwift入門篇

原創 2017-06-13

RxSwift 這個框架RP框架相信你應該不陌生了,在Objective-C中我們使用比較多的是ReactiveCocoa,從網上找到的入門知識比較零散,我現在就將從官方文檔學習的筆記作為一個記錄,也許對剛開始學習的你會有所幫助。如下就是我通過思維導圖繪制的框架大致內容:

RxSwift框架

從上圖可以看出,整個框架無外乎圍繞著:

  • Observable: 可觀察序列
  • Observer:觀察者
  • Subjects:觀察和觀察序列橋梁
  • Disposable:你可以把它看做一個ARC
  • Scheduler:任務執行線程

下面我們就圍繞著這幾大模塊介紹,首先介紹一下Observable:

Observable

在ReactiveX中,Observable<Element>代表的是一個可觀察序列,從字面意思可以看出這是在觀察者模式中的被觀察者,它會向觀察對象發送事件序列:

  • .Next(Element):新事件
  • .Error(error):帶有異常的事件完成序列
  • .Complete():正常事件完結序列

Observable大致需要了解一下知識,我們將圍繞到以下內容進行學習:


Observable需要學習

Observable 創建

  • Create:通過編程方式來創建可觀察對象,創建后的Observeble是可以接收到.onNext、.onError、.onComplete
create
----------  示例代碼  ----------
let observable = Observable<String>.create { (observer) -> Disposable in
   observer.onNext("hello RxSwift")
   observer.onCompleted()
   return Disposables.create {
       print("disposabled")
   }
}
observable.subscribe { (event) in
   print("Operator: create \(event)")
}.dispose()  

----------  運行結果  ----------
Operator: create next(hello RxSwift)
Operator: create completed
disposabled
  • Defer:延時創建Observable對象,當subscribe的時候才去創建,它為每一個Observer創建一個新的Observable,也就是說每個訂閱者訂閱的對象都是內容相同但是完全獨立的序列;deferr采用一個Factory函數型作為參數,Factory函數返回的是Observable類型。這也是其延時創建Observable的主要實現
defer
----------  示例代碼  ----------
let defObservable = Observable<String>.deferred { () -> Observable<String> in
    return Observable.create({ (observer) -> Disposable in
        observer.onNext("create")
        observer.onCompleted()
        return Disposables.create {
            print("disposed")
        }
    })
}

defObservable.subscribe { (event) in
    print("one  --   \(event)")
}

defObservable.subscribe { (event) in
    print("two  --   \(event)")
}

----------  運行結果  ----------
one  --   next(create)
one  --   completed
disposed
two  --   next(create)
two  --   completed
disposed

通過上述例子,相信你已經看出來了在前面說到的:defer創建會為每個Observer創建一個新的獨立的Observable,并且他們具有相同內容,但是好像并沒有體現出defer延遲創建,那么請你注意下面這兩個例子的對比

---------- 示例非defer,這里可能會用到后面講的內容 ----------
var value: String?
let observable = Observable<String>.from(optional: value)
value = "hello RxSwift"
observable.subscribe { (event) in
    print(event)
}.dispose()

---------- 運行結果 ----------
completed

上述結果并沒有像我們想象中的那樣也會打印出 onNext事件,這個是為什么呢? 因為在我們訂閱的時候,數據未必已經初始化完成,現在我們把這個例子使用defer重新測試一下:

---------- 示例,通過defer改寫上面 ----------
var value: String?
let observable = Observable<String>.deferred { () -> Observable<String> in
    return Observable<String>.from(optional: value)
}
value = "hello RxSwift"
observable.subscribe { (event) in
    print(event)
}.dispose()

---------- 運行結果 ---------
next(hello RxSwift)
completed

看到了如期打印出來的onNext結果,這可能才會是你想達到的效果,具體defer還是需要看使用場景,只有在場景中慢慢體會。

  • Of / From :這兩個方法都是把一個對象或者數據轉換為可觀察序列,這在你使用Swift中的SequenceType時很有用
of/from
---------- of 示例 ----------
Observable<String>.of("hello", "RxSwift").subscribe { (event) in
    print("operator: of     \(event)")
}.dispose() 

---------- 運行結果 ----------
operator: of     next(hello)
operator: of     next(RxSwift)
operator: of     completed
---------- from 示例 ----------
Observable<String>.from(["hello", "RxSwift"]).subscribe { (event) in
    print("operator: from    \(event)")
}.dispose()

----------- 運行結果 ----------
operator: from    next(hello)
operator: from    next(RxSwift)
operator: from    completed
  • Just:將一個對象或者一個Sequence轉換為 一個 可觀察序列,請注意這里與From是完全不相同的:From是轉換為一個或者多個可觀察序列(這取決于你是要將一個還是一個序列進行轉換)。也就是說Just只能包含一個觀察序列,請注意與上面例子結果進行對比
just
---------- Just 示例對比 ----------
Observable<String>.from(["hello", "RxSwift"]).subscribe { (event) in
    print("operator: just    \(event)")
}
        
Observable<Array<String>>.just(["hello", "RxSwift"]).subscribe { (event) in
    print("operator: just    \(event)")
}

--------- 運行結果 ----------
operator: from    next(hello)
operator: from    next(RxSwift)
operator: from    completed
operator: just    next(["hello", "RxSwift"])
operator: just    completed
  • Interval:創建一個可觀察序列,以特定的時間間隔釋放一系列整數(E -> Int/NSInteger)
----------- 示例 ---------
Observable<Int>.interval(1, scheduler: MainScheduler.instance)
    .take(3)   // 發送3次Next,后面再講到此方法
    .subscribe { (event) in
        print("operator: interval     \(event)")
 }

----------- 運行結果 ---------
operator: interval     next(0)
operator: interval     next(1)
operator: interval     next(2)
operator: interval     completed
  • Range:創建一個可觀察到的,發射特定序列整數的范圍(E -> Int/NSInteger)
range
---------- 示例 ----------
Observable<Int>.range(start: 1, count: 5).subscribe { (event) in
    print("operator: range    \(event)")
}.dispose()

---------- 運行結果 ---------
operator: range    next(1)
operator: range    next(2)
operator: range    next(3)
operator: range    next(4)
operator: range    next(5)
operator: range    completed
  • Repeat: 創建一個可多次發送特定item的Observable
repeat
---------- 示例 ----------
Observable<String>.repeatElement("hello RxSwift")
    .take(3)
    .subscribe { (event) in
         print("operator: repeat      \(event)")
}.dispose()

---------- 運行結果 --------
operator: repeat      next(hello RxSwift)
operator: repeat      next(hello RxSwift)
operator: repeat      next(hello RxSwift)
operator: repeat      completed
  • Start:
start
  • Timer:在指定的時間后,發送一個特定的Item (E -> Int/NSInteger),請注意這里與Interval的區別(Interval是發送一系列特定Item,而Timer只會發送一個)
timer
---------- 示例 ---------
Observable<Int>.timer(1, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: timer     \(event)")
}

---------- 運行結果 ---------
operator: timer     next(0)
operator: timer     completed
  • Empty: 只會發送一個Complete事件
empty創建
---------- 示例 ----------
Observable<Int>.empty().subscribe { (event) in
    print("operator: empty      \(event)")
}.dispose()

---------- 運行結果 ----------
operator: empty      completed
  • Never:你將不會收到任何事件,并且它將永遠不會終止
never創建
  • Generate:其實是實現了一個迭代器的效果,他有三個參數,第一個是初始值,第二個是條件(滿足條件之后就會繼續執行.Next事件,第三個是迭代器,每次都會返回一個E類型,知道不滿足條件為止
---------- 示例 ----------
Observable<Int>.generate(initialState: 0, condition: { (element: Int) -> Bool in
    return element < 10
}, iterate: { element -> Int in
    return element + 3
}).subscribe { (event) in
    print("operator: generate   \(event)")
}.dispose()

----------- 運行結果 ----------
operator: generate   next(3)
operator: generate   next(6)
operator: generate   next(9)
operator: generate   completed

上述例子表示的是:我有一個初始變量0, 此時滿足條件 < 10 ,那么就會執行迭代器,每次+3,直到不滿足條件為止

Observable 變換

  • Buffer:定期的將需要發射的Items手機到一個buffer的包中,分批次的發射這些包,而不是一次發射一個Item:例如你有[1, 2, 3, 4] ,你可以一次發射一個,也可以一次發射兩個Item或者三個...,你需要仔細的觀察下面的輸出結果,如果需要更好的理解還請你敲一遍代碼
buffer
---------- 示例1 一次發射1個Item事件 --------
Observable<Int>.of(1, 2, 3, 4)
    .buffer(timeSpan: 1, count: 1, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: buffer    \(event)")
    }.dispose()

---------- 運行結果 ---------
operator: buffer    next([1])
operator: buffer    next([2])
operator: buffer    next([3])
operator: buffer    next([4])
operator: buffer    next([])
operator: buffer    completed
---------- 示例2 一次發射3個Item事件 --------
Observable<Int>.of(1, 2, 3, 4)
    .buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: buffer    \(event)")
    }.dispose()

---------- 運行結果 ---------
operator: buffer    next([1, 2, 3])
operator: buffer    next([4])
operator: buffer    completed

還可以有其他多個不同發射Item事件,請仔細體會上述結果

  • Window:與Buffer類似,但是每次發射的不是Item,而是Observables序列(請注意與Buffer的結果比較):
window
------------ 示例 -----------
Observable<Int>.of(1, 2, 3, 4)
    .window(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: window     \(event)")
        // 這里event的element 是一個Observable
        event.element?.subscribe({ (event) in
            print("operator: window - subObservables    \(event)")
        }).dispose()
    }.dispose()

------------ 運行結果 -----------
operator: window     next(RxSwift.AddRef<Swift.Int>)
operator: window - subObservables    next(1)
operator: window - subObservables    next(2)
operator: window - subObservables    next(3)
operator: window - subObservables    completed
operator: window     next(RxSwift.AddRef<Swift.Int>)
operator: window - subObservables    next(4)
operator: window - subObservables    completed
operator: window     completed
  • FlatMap:將一個發射數據的Observable變換為多個Observables,然后將它們發射的數據合并后放進一個單獨的Observable。
flatMap

FlatMap操作符使用一個指定的函數對原始Observable發射的每一項數據執行變換操作,這個函數返回一個本身也發射數據的Observable,然后FlatMap合并這些Observables發射的數據,最后將合并后的結果當做它自己的數據序列發射

這個方法是很有用的,例如,當你有一個這樣的Observable:它發射一個數據序列,這些數據本身包含Observable成員或者可以變換為Observable,因此你可以創建一個新的Observable發射這些次級Observable發射的數據的完整集合

--------- 示例1 ---------
// 我需要在每一個Item后跟一個新的Item叫做RxSwift
Observable<Int>.of(0, 1, 2)
    .flatMap { (element: Int) -> Observable<String>  in
        return Observable<String>.of("\(element)", "RxSwift")
    }
    .subscribe { (event) in
        print("operator: flatMap     \(event)")
    }.dispose()

--------- 運行結果 -------
operator: flatMap     next(0)
operator: flatMap     next(RxSwift)
operator: flatMap     next(1)
operator: flatMap     next(RxSwift)
operator: flatMap     next(2)
operator: flatMap     next(RxSwift)
operator: flatMap     completed
  • GroupBy:將一個Observable分拆為一些Observables集合,它們中的每一個發射原始Observable的一個子序列
groupBy
----------- 示例 --------
// 我需要將奇數偶數分成兩組
Observable<Int>.of(0, 1, 2, 3, 4, 5)
    .groupBy(keySelector: { (element) -> String in
        return element % 2 == 0 ? "偶數" : "基數"
    })
    .subscribe { (event) in
        switch event {
        case .next(let group):
            group.asObservable().subscribe({ (event) in
                print("key: \(group.key)     \(event)")
            })
        default:
            print("")
        }
    }
    .dispose()

--------- 運行結果 ---------
key: 基數     next(1)
key: 偶數     next(2)
key: 基數     next(3)
key: 偶數     next(4)
key: 基數     next(5)
key: 偶數     completed
key: 基數     completed
  • Map:通過一個閉包將原來的序列轉換為一個新序列的操作
map
---------- 示例 ----------
Observable<String>.of("John", "Tony", "Tom")
    .map { return "hello " + $0}
    .subscribe { (event) in
        print("operator: map     \(event)")
    }.dispose()

---------- 運行結果 ----------
operator: map     next(hello John)
operator: map     next(hello Tony)
operator: map     next(hello Tom)
operator: map     completed
  • Scan:從字面意思可以看出是掃描,也就是說該方法會給出一個初始值(seed),每次通過一個函數將上一次的結果與序列中的Item進行處理,每處理完成都會發射.Next事件
scan
----------- 示例 ----------
Observable<String>.of("Rx", "Swift")
    .scan("hello ") { (acum, element) in
        return acum + element
    }.subscribe { (event) in
        print("operator: scan      \(event)")
    }.dispose()

---------- 運行結果 ----------
operator: scan      next(hello Rx)
operator: scan      next(hello RxSwift)
operator: scan      completed
  • Reduce:與上述Scan類似,都是初始一個Seed,每次通過函數將上一次的結果與序列中的Item進行處理,但是唯一不同的一點是,只會在最后發射一次.Next事件,將其拿來作數學計算很有用,這個我們將會在后面講到 (** 請注意與上述Scan的結果比較**)
reduce
---------- 示例 ----------
Observable<String>.of("Rx", "Swift")
    .reduce("hello ") { (accum, element) -> String in
        return accum + element
    }.subscribe { (event) in
        print("operator: reduce    \(event)")
    }.dispose()

---------- 運行結果 ----------
operator: reduce    next(hello RxSwift)
operator: reduce    completed

Observable 過濾器

  • Debounce:在規定的時間內過濾Item,如下圖:如果debounce開啟的時候此時2、3、4 Item正好到來,那么將無法收到它們的任何時間
debounce
----------- 示例 ----------
Observable<Int>.of(1, 2, 3, 4)
    .debounce(1, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: debounce     \(event)")
    }.dispose()

----------- 運行結果 ----------
operator: debounce     next(4)
operator: debounce     completed
  • Distinct:過濾掉可觀察到的重復Item(相信你在使用數據庫的時候回經常使用到distinct),在Swift中使用的是distinctUntilChanged,表示如果發射的事件與上一次不相同那么才會發射此次事件
distinctUntilChanged
---------- 示例 ----------
Observable<Int>.of(1, 2, 2, 2, 3)
    .distinctUntilChanged()
    .subscribe { (event) in
        print("operator: distict     \(event)")
    }.dispose()

---------- 運行結果 ----------
operator: distict     next(1)
operator: distict     next(2)
operator: distict     next(3)
operator: distict     completed
  • ElementAt:發射第 N 個Item
elementAt
----------- 示例 ----------
Observable<Int>.of(1, 2, 2, 3, 4)
    .elementAt(5)
    .subscribe { (event) in
        print("operator: elementAt    \(event)")
    }.dispose()

----------- 運行結果 -----------
operator: elementAt    next(3)
operator: elementAt    completed
  • Filter:僅發射謂詞測試通過的Items
filter
----------- 示例 -----------
Observable<Int>.of(9, 10, 11, 12)
    .filter { (element) -> Bool in
        element > 10
    }.subscribe { (event) in
        print("operator: filter    \(event)")
    }.dispose()

----------- 運行結果 -----------
operator: filter    next(11)
operator: filter    next(12)
operator: filter    completed
  • Skip:發射第N(包含N)之后的Items
skip
----------- 示例 -----------
Observable<Int>.of(9, 10, 11, 12)
    .skip(2)
    .subscribe { (event) in
        print("operator: skip    \(event)")
    }.dispose()

----------- 運行結果 ---------
operator: skip    next(11)
operator: skip    next(12)
operator: skip    completed
  • Take: 發射第N(不包含N)之前的Items,與Skip相反效果
take
----------- 示例 -----------
Observable<Int>.of(9, 10, 11, 12)
    .take(2)
    .subscribe { (event) in
        print("operator: take    \(event)")
    }.dispose()

---------- 運行結果 -----------
operator: take    next(9)
operator: take    next(10)
operator: take    completed
  • TakeLast: 發射第N(包含N)之后的Items,與Skip相同效果
take
----------- 示例 -----------
Observable<Int>.of(9, 10, 11, 12)
    .takeLast(2)
    .subscribe { (event) in
        print("operator: takeLast    \(event)")
    }.dispose()

---------- 運行結果 -----------
operator: takeLast    next(11)
operator: takeLast    next(12)
operator: takeLast    completed

結合多個Observables

  • Merge:將多個序列的Items合并為一個序列的Items
merge
----------- 示例 ----------
let observable1 = Observable<Int>.of(1, 3, 5)
let observable2 = Observable<Int>.of(2, 4)
Observable.merge(observable1, observable2)
    .subscribe { (event) in
        print("operator: merge      \(event)")
    }.dispose()

----------- 運行結果 ----------
operator: merge      next(1)
operator: merge      next(2)
operator: merge      next(3)
operator: merge      next(4)
operator: merge      next(5)
operator: merge      completed
  • StartWith:在發射序列Items前新增一個Item
startWith
----------- 示例 ----------
Observable<String>.of("  ", "RxSwift", "!")
    .startWith("hello")
    .reduce("") { (accum, element) -> String in
        return accum + element
    }.subscribe { (event) in
        print("operator: startWith    \(event)")
    }.dispose()

----------- 運行結果 ----------
operator: startWith    next(hello  RxSwift!)
operator: startWith    completed
  • Switch:當你的序列是一個事件序列的序列 (Observable<Observable<T>>) 的時候(也即是二維序列),可以使用 switch 將序列的序列轉換成一維,并且在出現新的序列的時候,自動切換到最新的那個序列上。也就是說會將前一個序列未發射的Item自動取消掉
switch
----------- 示例 ----------
let var1 = Variable(0)
let var2 = Variable(100)
        
// 序列的序列
let variable = Variable(var1.asObservable())
        
variable.asObservable()
    .switchLatest()
    .subscribe { (event) in
        print("operator: switchLatest   \(event)")
    }
        
var1.value = 1
        
variable.value = var2.asObservable()
var2.value = 200

----------- 運行結果 ----------
operator: switchLatest   next(0)
operator: switchLatest   next(1)
operator: switchLatest   next(100)
operator: switchLatest   next(200)
operator: switchLatest   completed
  • Zip:將多個序列的Items進行一一合并,但是需要注意的是,它會等到Item對其后合并,未對齊的會舍棄
zip
---------- 示例 -----------
let observable1 = Observable<Int>.of(1, 2, 3, 4, 5)
let observable2 = Observable<String>.of("A", "B", "C", "D")
        
Observable<String>.zip(observable1, observable2) { (e1: Int, e2: String) -> String in
    "\(e1)\(e2)"
}.subscribe { (event) in
    print("operator: zip     \(event)")
}.dispose()

---------- 運行結果 ----------
operator: zip     next(1A)
operator: zip     next(2B)
operator: zip     next(3C)
operator: zip     next(4D)
operator: zip     completed
  • CombineLatest:如果存在兩條事件隊列,需要同時監聽,那么每當有新的事件發生的時候,combineLatest 會將每個隊列的最新的一個元素進行合并。類似于zip,但是只有當原始的Observable中的每一個都發射了一條數據時zip才發射數據。CombineLatest則在原始的Observable中任意一個發射了數據時發射一條數據。當原始Observables的任何一個發射了一條數據時,CombineLatest使用一個函數結合它們最近發射的數據,然后發射這個函數的返回值
combineLatest
---------- 示例 ----------
let observable1 = Observable<Int>.of(1, 2, 3, 4, 5)
let observable2 = Observable<String>.of("A", "B", "C", "D")
Observable<String>.combineLatest(observable1, observable2, resultSelector: { (e1: Int, e2: String) -> String in
        "\(e1)\(e2)"
    }).subscribe { (event) in
        print("operator: combine    \(event)")
    }.dispose()

----------- 運行結果 ----------
operator: combine    next(1A)
operator: combine    next(2A)
operator: combine    next(2B)
operator: combine    next(3B)
operator: combine    next(3C)
operator: combine    next(4C)
operator: combine    next(4D)
operator: combine    next(5D)
operator: combine    completed

錯誤處理

  • Catch:在收到序列的異常事件時,通過返回另一個序列來持續發送非error事件
catchError
----------- 示例 -----------
Observable<UInt8>.create { (observer) -> Disposable in
        observer.onNext(0)
        observer.onError(CustomError())   // 這里自定義了一個Error
        return Disposables.create()
    }.catchError { (error) -> Observable<UInt8> in
        print(error)
        return Observable<UInt8>.of(1, 2)
    }.subscribe { (event) in
        print("operator: catchError    \(event)")
    }.dispose()

----------- 運行結果 ----------
operator: catchError    next(0)
RxDemo.(CustomError in _53A9E5DF100B211646D927F0B28DE79B)
operator: catchError    next(1)
operator: catchError    next(2)
operator: catchError    completed
  • Retry:出現錯誤事件后,重新發送所有事件信息
retry
---------- 示例 -----------
Observable<UInt8>.create { (observer) -> Disposable in
        observer.onNext(0)
        observer.onError(CustomError())
        return Disposables.create()
    }.retry(3)  // 重復三次
    .subscribe { (event) in
        print("operator: retry    \(event)")
    }.dispose()

----------- 運行結果 -----------
operator: retry    next(0)
operator: retry    next(0)
operator: retry    next(0)
operator: retry    error(RxDemo.(CustomError in _53A9E5DF100B211646D927F0B28DE79B))

Observable實用操作

  • Delay:延遲發射事件
delay
------------ 示例 ------------
print("start time: \(Date())")
Observable<Int>.of(1, 2, 1)
    .delay(1, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        if event.isCompleted {
            print("end time: \(Date())")
        }
        print("operator: delay    \(event)")
    }

------------ 運行結果 -----------
start time: 2017-06-12 06:10:32 +0000
operator: delay    next(1)
operator: delay    next(2)
operator: delay    next(1)
end time: 2017-06-12 06:10:33 +0000
operator: delay    completed
  • Do: 在一個序列的每個事件執行之前添加一個執行動作
do
---------- 示例 ----------
Observable<Int>.of(1, 2, 1)
    .do(onNext: { (_) in
        print("operator: do   previous next")
    }, onError: { (_) in
        print("operator: do   previous error")
    }, onCompleted: {
        print("operator: do   previous complete")
    }, onSubscribe: nil, onSubscribed: nil, onDispose: nil)
    .subscribe { (event) in
        print("operator: delay    \(event)")
    }.dispose()

---------- 運行結果 ---------
operator: do   previous next
operator: delay    next(1)
operator: do   previous next
operator: delay    next(2)
operator: do   previous next
operator: delay    next(1)
operator: do   previous complete
operator: delay    completed
  • ObserveOn:Observer在指定Scheduler中觀察序列事件
observeOn
----------- 示例 --------
Observable<Int>.of(1)
    .observeOn(ConcurrentDispatchQueueScheduler.init(queue: DispatchQueue(label: "test")))
    .subscribe { (event) in
        print("operator: observeOn  \(Thread.current.isMainThread)    \(event)")
    }

---------- 運行結果 ----------
operator: observeOn  false    next(1)
operator: observeOn  false    completed
  • Subscribe:訂閱事件.onNext 、.onError、.onCompleted
----------- 示例 ---------
Observable<String>.of("hello RxSwift").subscribe(onNext: { (element) in
        print("operator: onNext    \(element)")
    }, onError: { (error) in
        print("operator: onError   \(error)")
    }, onCompleted: {
        print("operator: onCOmpleted")
    }, onDisposed: nil)

----------- 運行結果 ----------
operator: onNext    hello RxSwift
operator: onCOmpleted
  • SubscribeOn:在指定的Scheduler中操作,參考ObserveOn
subscribeOn
----------- 示例 ---------
Observable<Int>.of(1)
    .subscribeOn(MainScheduler.instance)
    .subscribe { (event) in
        print("operator: observeOn  \(Thread.current.isMainThread)    \(event)")
    }

----------- 運行結果 ----------
operator: subscribeOn  true    next(1)
operator: subscribeOn  true    completed
  • TimeOut:一個序列在指定時間內未發射完成所有事件,那么將會進入.onError
timeOut
---------- 示例 --------
Observable<Int>.of(1)
    .delay(2, scheduler: MainScheduler.instance)
    .timeout(1, scheduler: MainScheduler.instance)
    .subscribe { (event) in
        print("operator: timeout    \(event)")
    }

---------- 運行結果 ----------
operator: timeout    error(Sequence timeout.)

條件運算符和布爾類型運算符

  • DefaultIfEmpty:如果是序列中沒有任何Item,那么給定一個default
---------- 示例 -----------
Observable<Int>.empty()
    .ifEmpty(default: 0)
    .subscribe({ (event) in
        print("operator: ifEmpty    \(event)")
    })

----------- 運行結果 ---------
operator: ifEmpty    next(0)
operator: ifEmpty    completed
  • SkipUntil:丟棄掉第一個序列的所有Items,直到第二個序列的Item出現
skipUntil
--------- 示例 ----------
Observable<String>.of("A", "B", "C")
    .skipUntil(Observable<String>.of("D"))
    .subscribe { (event) in
        print("operator: skipUntil    \(event)")
    }

--------- 運行結果 --------
operator: skipUntil    next(B)
operator: skipUntil    next(C)
operator: skipUntil    completed
  • SkipWhile:丟棄掉所有的Items,直到滿足某個不滿足條件的Item出現
skipWhile
---------- 示例 ---------
Observable<String>.of("AD", "BD", "CD")
    .skipWhile({ (element) -> Bool in
        element.contains("A")
    })
    .subscribe { (event) in
        print("operator: skipWhile    \(event)")
    }.dispose()

---------- 運行結果 ---------
operator: skipWhile    next(BD)
operator: skipWhile    next(CD)
operator: skipWhile    completed
  • TakeUntil:取得第一個序列所有Items,直到第二個序列發射Item或者終止
takeUntil
---------- 示例 --------
Observable<Int>.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
    .takeUntil(Observable<Int>.empty())
    .subscribe { (event) in
        print("operator: takeUntil    \(event)")
    }.dispose()
  • TakeWhile:取得第一個序列的所有Items,直到出現不滿足條件的Item (請仔細體會與SkipWhile的不同之處)
takeWhile
----------- 示例 ---------
Observable<Int>.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
    .takeWhile({ (element) -> Bool in
        element < 5
    })
    .subscribe { (event) in
        print("operator: takeUntil    \(event)")
    }.dispose()

--------- 運行結果 -------- 
operator: takeWhile    next(1)
operator: takeWhile    next(2)
operator: takeWhile    next(3)
operator: takeWhile    next(4)
operator: takeWhile    completed

連接操作

  • Publish:將一個普通的序列轉換為可連接序列
publish
  • RefCount:使一個可連接序列表現為一個普通序列
refCount
  • Replay:保證所有的Observers所觀察到的事件Items都是相同的,即使它們已經在序列事件已經發射之后才訂閱的 (具體使用將在下一章節的Subjects中講到)
replay

Observer

  • Observer作為觀察者,用于來訂閱Observable,它可以用來通知.onNext、.onError、.onCompleted
--------- 示例 --------
Observable<String>.create { (observer) -> Disposable in
    observer.on(.next("hello RxSwift"))
    observer.onError(CustomError())
        return Disposables.create {
            print("disposable")
        }
    }.subscribe { (event) in
        print(event)
    }.dispose()

--------- 運行結果 ---------
next(hello RxSwift)
error(RxDemo.(CustomError in _53A9E5DF100B211646D927F0B28DE79B))
  • AnyObserver使用:
--------- 示例 ----------
let observer1 = AnyObserver<Int> { (event) in
    print(event)
}
        
let observer2 = AnyObserver(observer1)
        
Observable<Int>.of(1, 2, 3)
    .subscribe(observer2)
    .dispose()

---------- 運行結果 --------
next(1)
next(2)
next(3)
completed

Subject

Subject在ReactiveX的一些實現中扮演了一種橋梁或者代理的角色,它既可以作為Observer也可以作為Observable來使用。作為觀察者來說它可以訂閱一個或者多個可觀察序列,作為可觀察者來說它可以通過Items的reemitting來觀察,并且還可以發射新的Items事件,我們將從如下四個Subject進行學習:

image
  • AnySubject:僅僅只發送訂閱之后的最后一個Item以及.onCompleted,如果出現錯誤,那么僅僅將只發送.onError
image
錯誤
  • ReplaySubject:如果一個Observer訂閱了ReplaySubject,那么它將收到訂閱前(在bufferSize大小內)以及訂閱后的所有Items,不管Observer何時訂閱的
image
---------- 示例 -----------
let replay = ReplaySubject<Int>.create(bufferSize: 3)

replay.onNext(0)
replay.onNext(1)
replay.onNext(2)
replay.onNext(3)
replay.subscribe { (event) in
    print("Replay  first       \(event)")
}
replay.onNext(4)

replay.subscribe { (event) in
    print("Replay  second       \(event)")
}
replay.onNext(5)
replay.onCompleted()

---------- 運行結果 ----------
Replay  first       next(1)
Replay  first       next(2)
Replay  first       next(3)
Replay  first       next(4)
Replay  second       next(2)
Replay  second       next(3)
Replay  second       next(4)
Replay  first       next(5)
Replay  second       next(5)
Replay  first       completed
Replay  second       completed

請仔細查看上面的運行結果你可以發現:上述replay被兩次訂閱了之后都會收到訂閱的Items,但是收到訂閱之前的Items是有size限制的,這就與你設置的bufferSize大小有關了。訂閱之后的Items是可以完全收到的

  • PublishSubject:與BehaviorSubject有略微不同,從字面意思可以看出Publish是發布,那么就意味著如果一個Observer訂閱了PublishSubject,它就將收到訂閱之后的所有事件,但是不包括訂閱之前的事件(你也可以把他看成一個bufferSize=0的ReplaySubject)
image
----------- 示例 ---------
let publish = PublishSubject<Int>()
        
publish.onNext(1)
publish.onNext(2)
publish.subscribe { (event) in
    print("Publish       \(event)")
}
publish.onNext(3)
publish.onNext(4)
publish.onCompleted()

---------- 運行結果 ---------
// 從結果可以看出,訂閱之前的所有Item是收不到的,請體會與BehaviorSubject之間差異
Publish       next(3)   
Publish       next(4)
Publish       completed
  • BehaviorSubject:如果一個Observer訂閱了BehaviorSubject之后,那么它就將收到最近的事件,并且也能夠收到在訂閱之后發射的事件Item (你也可以把它看成一個bufferSize=1 的ReplaySubject)


    image
----------- 示例 ----------
let behavior = BehaviorSubject<Int>(value: 0)
        
behavior.onNext(1)
behavior.onNext(2)
behavior.onNext(3)
let disposable = behavior.subscribe { (event) in
    print("Behavior       \(event)")
}
behavior.onNext(4)
behavior.onCompleted()

---------- 運行結果 -----------
Behavior       next(3)      // 收到最近Item事件
Behavior       next(4)      // 收到訂閱之后所有事件
Behavior       completed
  • Variable:與BehaviorSubject類似,但是比較特殊的一點就是:在.onError之后它不會終止,只會等待到.onCompleted之后才會被deallocated

注意:至此Subject基本就是這些特殊內容,對于這些特殊內容我建議你敲代碼,看結果來仔細體會它們之間的不同與相同之處

Scheduler

對于Scheduler來說,我們需要了解Concurrent(并行)、Serial(串行)Scheduler就可以了,如下為所有Scheduler腦圖:

image
  • Scheduler:當你在多線程的時候你會用到這個Scheduler

在上面的章節相信你已經熟悉了observeOn/subscribeOn,這里我們就直接上來個例子介紹:

----------- 示例 -----------
Observable<Int>.of(1, 2, 3, 4)
            .observeOn(SerialDispatchQueueScheduler(internalSerialQueueName: "test"))
    .map { (element) -> Int in
        print("scheduler:map  -->  Main Thread: \(Thread.current.isMainThread)")
                return element * 2
    }
    .subscribeOn(MainScheduler.instance)
    .observeOn(MainScheduler.instance)
    .subscribe { (event) in
        print("scheduler:subscribe  -->  Main Thread: \(Thread.current.isMainThread)")
        print("scheduler     \(event)")
    }

---------- 運行結果 -----------
scheduler:map  -->  Main Thread: false
scheduler:map  -->  Main Thread: false
scheduler:map  -->  Main Thread: false
scheduler:map  -->  Main Thread: false
scheduler:subscribe  -->  Main Thread: true
scheduler     next(2)
scheduler:subscribe  -->  Main Thread: true
scheduler     next(4)
scheduler:subscribe  -->  Main Thread: true
scheduler     next(6)
scheduler:subscribe  -->  Main Thread: true
scheduler     next(8)
scheduler:subscribe  -->  Main Thread: true
scheduler     completed

Disposable

什么時候使用Disposable呢?我個人理解就是你訂閱了一個可觀察序列,如果有特殊需求你需要提前取消訂閱時使用。也就是說Disposable是用來取消訂閱的一個工具

image
  • 創建:通過Disposables工具創建
let dis1 = Disposables.create()

let dis2 = Disposables.create {
    print("在Dispose之前所做一些工作")
}

let dis3 = Disposables.create([dis1, dis2])
  • dispose:通過.dispose()取消或者添加到DisposeBag(你可以將它看成一個非ARC機制下的AutoReleasePool
let disposable = Observable<Int>.of(0, 1, 2)
    .subscribe { (event) in
    print(event)
}
        
disposable.dispose()
        
// 或者
disposable.addDisposableTo(DisposeBag())

至此,RxSwift的入門筆記到此結束,接下來我會繼續介紹RxSwift使用詳解篇相關學習筆記,敬請關注

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容