RxSwift使用手册

A simple introduction RxSwift essay but absolutely in detail, and practical

🇨🇳中文介绍

Requirements

  • iOS 8.0+
  • Xcode 8+
  • Swift 3.0

Observable

Observable<Element>是一个观察者模式中被观察的对象,相当于一个事件序列,会向订阅者发送新产生的事件信息。

Producer

Sequence

Sequence把一系列元素转换为事件序列

let sequenceOfElements = Observable.of(1,2,3,4)
        
        _ = sequenceOfElements.subscribe{
        
            event in
            print(event)
        }

运行结果如下:


Sequence

AnonymousObservable

AnonymousObservable继承自Producer,Producer实现了线程调度功能,可以安排线程来执行run方法,因此AnonymousObservable是可以运行在指定线程中Observable。

let generated = Observable.generate(
            initialState: 0, condition: {$0<20}, iterate: {$0+4}
        )
        
        _ = generated.subscribe{
        
            print($0)
        }

运行结果如下:

Generated

Error

Error,顾名思义,是做错误处理的,创建一个不发送任何 item 的 Observable。

let error = NSError(domain:"Test",code:-1,userInfo:nil)
        
        let erroredSequence = Observable<Any>.error(error)
        
        _ = erroredSequence.subscribe{
        
            print($0)
        }

运行结果如下:

Error

Deferred

deferred会等到有订阅者的时候再通过工厂方法创建Observable对象,每个订阅者订阅的对象都是内容相同而完全独立的序列。

let deferredSequence: Observable<Int> = Observable.deferred {
            print("creating")
            return Observable.create { observer in
                print("emmiting")
            
                observer.onNext(0)
                observer.onNext(1)
                observer.onNext(2)
                
                return Disposables.create()
            }
        }
        
        _ = deferredSequence
            .subscribe { event in
                print(event)
        }
        
        _ = deferredSequence
            .subscribe { event in
                print(event)
        }

运行结果如下:

Deferred

Empty

empty创建一个空的序列。它仅仅发送.Completed消息

 let emptySequence = Observable<Int>.empty()
        
        _ = emptySequence.subscribe{
        
            event in
            print(event)
        }

运行结果如下:

Empty

Never

never创建一个序列,该序列永远不会发送消息,.Complete消息也不会发送

 let neverSequence = Observable<Int>.never()
        
        _ = neverSequence.subscribe{
        
            _ in
            print("这句话永远都不会被打印,那干嘛要写呢?")
        }

什么都不会打印出来。

Just

just代表只包含一个元素的序列。它将向订阅者发送两个消息,第一个消息是其中元素的值,另一个是.Completed

 let singleElementSequence = Observable.just("iOS")
        
        _ = singleElementSequence.subscribe{
        
            print($0)
        }

运行结果如下:

Just

PublishSubject

PublishSubject会发送订阅者从订阅之后的事件序列。

 let subject = PublishSubject<Int>()
        
        _ = subject.subscribe{
        
            print($0)
        }
        
        subject.onNext(1)
        subject.onNext(2)
        subject.onNext(3)
        subject.onNext(4)

运行结果如下:


PublishSubject

ReplaySubject

ReplaySubject在新的订阅对象订阅的时候会补发所有已经发送过的数据队列,bufferSize是缓存区的大小,决定了补发队列的最大值。如果bufferSize是1,那么新的订阅着出现的时候就会补发上一个事件,如果是2,则补两个,以此类推。

 let subject1 = ReplaySubject<Int>.create(bufferSize: 2)
        
        _ = subject1.subscribe{ event in
            
        print("1->\(event)")
            
        }
        
        subject1.onNext(1)
        subject1.onNext(2)
        
        _ = subject1.subscribe{ event in
            
            print("2->\(event)")
            
        }
        subject1.onNext(3)
        subject1.onNext(4)

运行结果如下:


ReplaySubject

BehaviorSubject

BehaviorSubject在新的订阅对象订阅的时候会发送最近发送的事件,如果没有则发送一个默认值。

  let subject = BehaviorSubject(value: "z")
       
        _ = subject.subscribe{
        
            event in
            print("1 -> \(event)")
        }
        
        subject.onNext("a")
        subject.onNext("b")
        _ = subject.subscribe{
            
            event in
            print("2 -> \(event)")
        }

        subject.onNext("c")
        subject.onCompleted()

运行结果如下:

BehaviorSubject

Variable

variable是基于BehaviorSubject的一层封装,它的优势是:不会被显式终结。即:不会收到.Complete.Error这类的终结事件,它会主动在析构的时候发送.Complete

let variable = Variable("z")
        
        _ = variable.asObservable().subscribe{
        
            event in
            
            print("1 -> \(event)")
            
        }
        
        variable.value = "a"
        
        variable.value = "b"
        
        _ = variable.asObservable().subscribe{
            
            event in
            
            print("2 -> \(event)")
            
        }
        
        variable.value = "c"

运行结果如下:


Variable

Transforming Observables

Transforming Observables对序列做一些转换。

Map

map就是对每个元素都用函数做一次转换,挨个映射一遍。

let originalSequence = Observable.of(1,2,3)
        
        _ = originalSequence.map{
        
            number in
            number * 2
            }.subscribe{
        
                print($0)
        }

运行结果如下:


Map

FlatMap

flatMap将每个Observable发射的数据变换为Observable的集合,然后将其降维排列成一个Observable

let sequenceInt = Observable.of(1,2,3)
        
        let sequenceString = Observable.of("A","B","C","D","E","F","iOS")
        
        _ = sequenceInt.flatMap{
        
            (event:Int) -> Observable<String> in
            print("From sequentInt \(event)")
            return sequenceString
            }.subscribe{
        
                print($0)
        }

运行结果如下:


FlatMap

Scan

scanObservable发射的每一项数据应用一个函数,然后按顺序依次发射一个值。

   let sequenceToSum = Observable.of(0,1,2,3,4,5)
    
        _ = sequenceToSum.scan(0){
        
            acum ,elem in
            acum + elem
            }.subscribe{
        
                print($0)
        }

运行结果如下:


Scan

Filtering Observables

Filetering Observables对序列进行过滤

Filter

filter只会让符合条件的元素通过

let subscription = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
            .filter{
        
                $0 % 2 == 0
            }.subscribe{
        
                print($0)
        }

运行结果如下:

Filter

DistinctUntilChanged

distinctUntilChanged会废弃掉重复的事件

_ = Observable.of(1,1,1,1,1,1,1,1,1,2,2,3,3,4,4,5,5,5,6,6,6,6,6)
            .distinctUntilChanged()
            .subscribe{
        
            print($0)
        }

运行结果如下:

DistinctUntilChanged

Take

take只获取序列中的前n个事件,在满足数量之后会自动.Completed

_ = Observable.of(1,5,6,7,2,4,6,8,41,2)
        .take(4)
            .subscribe{
        
                print($0)
        }

运行结果如下:

Take

Combination operators

Combination operators是关于序列的运算,可以将多个序列源进行组合,拼装成一个新的事件序列。

StartWith

startWith会在队列开始之前插入一个事件元素

  _ = Observable.of(1,2,3)
        .startWith(0)
            .subscribe{
        
                print($0)
        }

运行结果如下:


StartWith

CombineLatest

CombineLatest如果存在两件事件队列,需要同时监听,那么每当有新的事件发生的时候,combineLatest会将每个队列的最新一个元素进行合并。

let observer1 = PublishSubject<String>()
        
        let observer2 = PublishSubject<Int>()
        
        _ = Observable.combineLatest(observer1, observer2) {
        
            "\($0)\($1)"
            }.subscribe{
        
                print($0)
        }
        
        observer1.onNext("iOS")
        
        observer2.onNext(6)
        
        observer1.onNext("Swift")
        
        observer2.onNext(66)
        
        observer1.onNext("Rx")
        
        observer2.onNext(666)

运行结果如下:

CombineLatest1

为了能够产生结果,两个序列中都必须保证至少有一个元素

 let observer1 = Observable.just(2)
        
        let observer2 = Observable.of(0,1,2,3,4)
        
        _ = Observable.combineLatest(observer1, observer2){
        
            $0 * $1
            }.subscribe{
        
                print($0)
        }

运行结果如下:

CombineLatest2

CombineLatest也有超过两个参数的版本

 let observer1 = Observable.just(2)
        
        let observer2 = Observable.of(0,1,2,3)
        
        let observer3 = Observable.of(0,1,2,3,4)
        
        _ = Observable.combineLatest(observer1, observer2, observer3){
        
            ($0 + $1) * $2
            }.subscribe{
        
                print($0)
        }

运行结果如下:

CombineLatest3

CombineLatest可以作用于不同的数据类型

 let intObserver = Observable.just(2)
        
        let stringObserver = Observable.just("ios")
        
        _ = Observable.combineLatest(intObserver, stringObserver){
        
            "\($0)" + $1
            }.subscribe{
        
                print($0)
        }

运行结果如下:

CombineLatest4

Zip

zip合并两条队列,不过它会等到两个队列的元素一一对应地凑齐之后再合并

let stringObserver = PublishSubject<String>()
        
        let intObserver = PublishSubject<Int>()
        
        _ = Observable.zip(stringObserver, intObserver){
        
            "\($0) \($1)"
            }.subscribe{
        
                print($0)
        }
        
        stringObserver.onNext("iOS")
        
        intObserver.onNext(6)
        
        stringObserver.onNext("swift")
        
        intObserver.onNext(66)
        
        stringObserver.onNext("Rx")
        
        intObserver.onNext(666)
        
        stringObserver.onNext("不会打印")

运行结果如下:

Zip

Merge

merge合并多个Observables的组合成一个

 let subject1 = PublishSubject<Int>()
        
        let subject2 = PublishSubject<Int>()
        
        _ = Observable.of(subject1,subject2)
        .merge()
            .subscribe{
        
                event in
                print(event)
        }
        
        subject1.onNext(20)
        
        subject1.onNext(40)
        
        subject1.onNext(60)
        
        subject2.onNext(1)
        
        subject1.onNext(80)
        
        subject1.onNext(100)
        
        subject2.onNext(2)

运行结果如下:

Merge1

假如只开一条线程

  let subject1 = PublishSubject<Int>()
        
        let subject2 = PublishSubject<Int>()
        
        _ = Observable.of(subject1,subject2)
        .merge(maxConcurrent: 1)
            .subscribe{
        
                event in
                print(event)
        }
        
        subject1.onNext(20)
        
        subject1.onNext(40)
        
        subject1.onNext(60)
        
        subject2.onNext(1)
        
        subject1.onNext(80)
        
        subject1.onNext(100)
        
        subject2.onNext(2)

运行结果如下:

marge2

SwitchLatest

switchLatest将一个发射多个ObservablesObservable转换成另一个单独的Observable,后者发射那些Observables最近发射的数据项

 let var1 = Variable(0)
        
        let var2 = Variable(200)
        
        let var3 = Variable(var1.asObservable())
        
        _ = var3
            .asObservable()
            .switchLatest()
            .subscribe{
                
                print($0)
        }
        
        var1.value = 1
        
        var1.value = 2
        
        var1.value = 3
        
        var1.value = 4
        
        var3.value = var2.asObservable()
        
        var2.value = 201
        
        var1.value = 5
        
        var1.value = 6
        
        var1.value = 7

运行结果如下:

SwitchLatest

Error Handing Operators

Error Handing Operators对从Observable发射的error通知做出响应或者从错误中恢复,简称错误处理

CatchError

catchError收到error通知之后,转而发送一个没有错误的序列

let sequenceThatFails = PublishSubject<Int>()
        
        let recoverySequence = Observable.of(100,200,300,400)
        
        _ = sequenceThatFails
            .catchError{
        
                error in
                return recoverySequence
            }.subscribe{
        
                print($0)
        }
        
        sequenceThatFails.onNext(1)
        
        sequenceThatFails.onNext(2)
        
        sequenceThatFails.onNext(3)
        
        sequenceThatFails.onNext(4)
        
        sequenceThatFails.onError(NSError(domain: "Test", code: 0, userInfo: nil))

运行结果如下:


CatchError1

另一种用法

let sequenceThatFails = PublishSubject<Int>()
        
        _ = sequenceThatFails
        .catchErrorJustReturn(100)
            .subscribe{
        
                print($0)
        }
        
        sequenceThatFails.onNext(1)
        
        sequenceThatFails.onNext(2)
        
        sequenceThatFails.onNext(3)
        
        sequenceThatFails.onNext(4)
        
        sequenceThatFails.onError(NSError(domain: "Test", code: 0, userInfo: nil))

运行结果如下:

CatchError2

Retry

retry,如果原始的Observable遇到错误,重新订阅。

var count = 1
        
        let funnyLookingSequence = Observable<Int>.create{
        
            observer in
            let error = NSError(domain: "Test", code: 0, userInfo: nil)
            
            observer.onNext(0)
            
            observer.onNext(1)
            
            observer.onNext(2)
            
            if count < 2 {
            
                observer.onError(error)
                
                count += 1
                
            }
            
            observer.onNext(3)
            
            observer.onNext(4)
            
            observer.onNext(5)
            
            observer.onCompleted()
            
            return Disposables.create()
        }
        
        _ = funnyLookingSequence
        .retry()
            .subscribe{
        
                print($0)
        }
        
        

运行结果如下:

Retry

Observable Utility Operators

Observable Utility Operators辅助工具

Subscribe

subscribe前面已经接触到了,有新的事件就会触发

let sequenceOfInts = PublishSubject<Int>()
        
        _ = sequenceOfInts
            .subscribe{
        
                print($0)
        }
        
        sequenceOfInts.onNext(1)
        
        sequenceOfInts.onCompleted()

运行结果如下:

Subscribe

SubscribeNext

subscribeNext

let sequenceOfInts = PublishSubject<Int>()
        
        _ = sequenceOfInts
            .subscribe(onNext:{
            
                print($0)
            })
        
        sequenceOfInts.onNext(1)
        
        sequenceOfInts.onCompleted()

运行结果如下:

SubscribeNext

SubscribeCompleted

subscribeCompleted

 let sequenceOfInts = PublishSubject<Int>()
        
        _ = sequenceOfInts
            .subscribe(onCompleted:{
            
                print("已经完成了")
            })
        
        sequenceOfInts.onNext(1)
        
        sequenceOfInts.onCompleted()

运行结果如下:

SubscribeCompleted

SubscribeError

subscribeError

let sequenceOfInts = PublishSubject<Int>()
        
        _ = sequenceOfInts
            .subscribe( onError:{
            
                error in
                print(error)
            })
        
        sequenceOfInts.onNext(1)
        
        sequenceOfInts.onError(NSError(domain: "Test", code: -1, userInfo: nil))

运行结果如下:

SubscribeError

DoOn

doOn注册一个操作来监听事件的生命周期

 let sequenceOfInts = PublishSubject<Int>()
        
        
        _ = sequenceOfInts.do(onNext:
            {
                print("监听 event \($0)")
        },  onCompleted:
            {
                print("监听 event \($0)")
        }).subscribe{
        
            print($0)
        }
        
        sequenceOfInts.onNext(1)
        
        sequenceOfInts.onCompleted()

运行结果如下:

DoOn

Conditional and Boolean Operators

Conditional and Boolean Operators条件和布尔操作,可用操作符根据条件发射或变换Observables,或者对他们做布尔运算

TakeUntil

takeUntil当第二个Observable发送数据之后,丢弃第一个Observable在这之后的所有信息

 let originalSequence = PublishSubject<Int>()
        let whenThisSendsNextWordStops = PublishSubject<Int>()
        
        _ = originalSequence.takeUntil(whenThisSendsNextWordStops).subscribe{
        
            print($0)
        }
        
        originalSequence.onNext(1)
        originalSequence.onNext(2)
        originalSequence.onNext(3)
        originalSequence.onNext(4)
        originalSequence.onNext(5)
        originalSequence.onNext(6)
        
        whenThisSendsNextWordStops.onNext(1)
        originalSequence.onNext(8)

运行结果如下:

TakeUntil

TakeWhile

takeWhile发送原始Observable的数据,直到一个特定的条件false

 let sequence = PublishSubject<Int>()
        
        _ = sequence
            .takeWhile{
        
                event in
                event < 4
            }.subscribe{
        
                print($0)
        }
        
        sequence.onNext(1)
        
        sequence.onNext(2)
        
        sequence.onNext(3)
        
        sequence.onNext(4)
        
        sequence.onNext(5)

运行结果如下:


TakeWhile

Mathematical and Aggregate Operators

Mathematical and Aggregate Operators算数和聚合
concat合并两个或者以上的Observable的消息,并且这些消息的发送时间不会交叉。

 let var1 = BehaviorSubject(value: 0)
        
        let var2 = BehaviorSubject(value: 200)
        
        let var3 = BehaviorSubject(value: var1)
        
        _ = var3
        .concat()
            .subscribe{
        
                print($0)
        }
        
        var1.onNext(1)
        
        var1.onNext(2)
        
        var1.onNext(3)
        
        var1.onNext(4)
        
        var3.onNext(var2)
        
        var2.onNext(201)
        
        var1.onNext(5)
        
        var1.onNext(6)
        
        var1.onNext(7)
        
        var1.onCompleted()
        
        var2.onNext(202)
        
        var2.onNext(203)
        
        var2.onNext(204)

运行结果如下:

Concat

Reduce

reduce按顺序对Observable发射的每项数据应用一个函数并发射最终的值。

 _ = Observable.of(0,1,2,3,4,5,6,7,8,9)
        .reduce(0, accumulator: +)
            .subscribe{
        
                print($0)
        }

运行结果如下:

Reduce

Connectable Observable Operators

Connectable Observable Operators连接操作

Delay

delay延迟操作

 let intObserver = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        
        _ = intObserver
            .subscribe{
        
                print("第一次走 \($0)")
        }
        

        DispatchQueue.main.asyncAfter(deadline: .now() + 5.0){
        
            _ = intObserver.subscribe{
            
                print("延迟5s走的 \($0)")
            }
        }
        

运行结果如下:

Delay

总结

欢迎各位同行入坑啊。。。哈哈哈哈。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,829评论 1 331
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,603评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,846评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,600评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,780评论 3 272
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,695评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,136评论 2 293
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,862评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,453评论 0 229
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,942评论 2 233
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,347评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,790评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,293评论 3 221
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,839评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,448评论 0 181
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,564评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,623评论 2 249

推荐阅读更多精彩内容