RxSwift 教程 学习

来源:互联网 发布:淘宝一元规则 编辑:程序博客网 时间:2024/05/16 10:38

RxSwift 教程 学习 基础总结

最近对RxSwift比较感兴趣, 看了一下官方的工程 , 跟其中的playground学习了基本的语法, 进入正题:
还要说一点, 一下内容大部分甚至绝大部分都是来自官方工程
有兴趣的clone下来看看
博客目前正在整理中可能有点慢, 我会尽快完成, 有兴趣可以先看我学习用的demo (如果感觉不错请给个star)
附上官网链接


目录

  • RxSwift 教程 学习 基础总结
    • 目录
    • 导入RxSwift
    • 基本语法
      • empty
      • never
      • just
      • sequenceOf
      • toObservable
      • create
      • error
      • generate
      • deferred
    • Subjects
      • PublishSubject
      • ReplaySubject
      • BehaviorSubject
      • Variable
    • function
      • map
      • FlatMap
      • Scan
      • Filter
      • DistinctUntilChanged
      • Take
      • Combining
      • StartWith
      • Zip
      • Merge
    • SwitchLatest
      • CatchError
      • Retry
      • Subscribe
      • DoOn
      • Take
      • Concat
      • reduce
    • 总结

导入RxSwift

如果你还没有吧RxSwift导入到你的工程中的话, 先导入工程(ps: 已经导入的请跳过)

基本语法

在这之前需要创建两个方法, 以供一会使用;

public func example(description: String, action: () -> ()) {    print("\n--- \(description) example ---")    action()}public func delay(delay:Double, closure:()->()) {    dispatch_after(        dispatch_time(            DISPATCH_TIME_NOW,            Int64(delay * Double(NSEC_PER_SEC))        ),        dispatch_get_main_queue(), closure)}

empty

empty看名字就知道, 他只会发送一个.Completed信号

example("empty", action: {            let emptySequence: Observable<Int> = Observable<Int>.empty()            let _ = emptySequence                .subscribe { event in                    print(event)            }        })

打印结果为:
— empty example —
Completed

never

never 是一个不会发送任何信号的序列

example("never") {            let neverSequence: Observable<Int> = Observable<Int>.never()            let _ = neverSequence                .subscribe { _ in                    print("This block is never called.")            }        }

打印结果为:
— never example —

just

just 只会发送两个信号, 首先是参数value, 然后是.Completed

example("just") {            let singleElementSequence:Observable<[String]>  = Observable.just(["aaa", "bbb"])            let _ = singleElementSequence                .subscribe { event in                    print(event)            }        }

打印结果为:
— just example —
Next([“aaa”, “bbb”])
Completed

sequenceOf

sequenceOf 是会吧传入的几个value 转化成信号 依次发出

example("sequenceOf") {            let sequenceOfElements = Observable.of(["aaa", "bbb"], ["ccc", "ddd"], ["eee", "fff"], ["ggg", "hhh"])            let _ = sequenceOfElements                .subscribe { event in                    print(event)            }        }

打印结果为:
— sequenceOf example —
Next([“aaa”, “bbb”])
Next([“ccc”, “ddd”])
Next([“eee”, “fff”])
Next([“ggg”, “hhh”])
Completed

toObservable

toObservable 可以把任意符合SequenceType的转换成Observable

example("toObservable") {            let sequenceFromArray = [1, 2, 3, 4, 5].toObservable()            let _ = sequenceFromArray                .subscribe { event in                    print(event)            }        }

打印结果:
— toObservable example —
Next(1)
Next(2)
Next(3)
Next(4)
Next(5)
Completed

create

create 手动创建一个信号, 信号内容可自行定义

example("create") {            let myJust = { (singleElement: Int) -> Observable<Int> in                return Observable.create { observer in                    let error = NSError(domain: "aaaaaa", code: 10000, userInfo: nil)                    observer.on(.Next(singleElement))                    if singleElement % 2 == 0 {                        observer.onError(error)                    } else {                        observer.on(.Completed)                    }                    return NopDisposable.instance                }            }            let _ = myJust(6)                .subscribe { event in                    print(event)            }        }

打印结果:
— create example —
Next(6)
Error(Error Domain=aaaaaa Code=10000 “(null)”)
Next(5)
Completed

error

error就是发送一个标志着错误的信号

 example("failWith") {            let error = NSError(domain: "Test", code: -1, userInfo: nil)            let erroredSequence: Observable<Int> = Observable.error(error)            let _ = erroredSequence                .subscribe { event in                    print(event)            }        }

打印结果:
— failWith example —
Error(Error Domain=Test Code=-1 “(null)”)

generate

generate生成一个条件环境, 把再这个环境中的符合条件的信号发送出去

 example("generate") {            let generated = Observable.generate(                initialState: 0,      // 初始状态                condition: { $0 < 3 }, // 条件                iterate: { $0 + 1 } // 重复            )            let _ = generated                .subscribe { event in                    print(event)            }        }

打印结果:
— generate example —
Next(0)
Next(1)
Next(2)
Completed

deferred

deferred是只有在有订阅的时候才会创建一个Observable, 这样的好处就在于创建Observable的时候 保证了数据是最新的, 例如:

example("deferred") {            var value = 1;            let normalCreate: Observable<Int> = Observable.just(value)            let deferredSequence: Observable<Int> = Observable.deferred {                return Observable.create { observer in                    observer.on(.Next(value))                    observer.on(.Completed)                    return NopDisposable.instance                }            }            value = 10            _ = normalCreate                .subscribe{                    print("normal-\($0)")            }            _ = deferredSequence                .subscribe {                    print("defer-\($0)")            }        }

打印结果:
— deferred example —
normal-Next(1)
normal-Completed
defer-Next(30)
defer-Completed

Subjects

Subjects 是一个既可以订阅又可以被订阅. 类似一个管道, 控制着内容的变化和输出
接下来的内容需要先定义一个辅助函数用于输出数据:

let disposeBag = DisposeBag()    func writeSequenceToConsole<O: ObservableType>(name: String, squence: O) {        squence.subscribe { e in            print("Subscription: \(name), event: \(e)")        }.addDisposableTo(disposeBag)    }

PublishSubject

PublishSubject 的订阅者只会接收到从它订阅以后发送的信号

example("PublishSubject") {            let subject = PublishSubject<String>()            self.writeSequenceToConsole("1", squence: subject)            subject.onNext("a")            subject.onNext("b")            self.writeSequenceToConsole("2", squence: subject)            subject.onNext("c")            subject.onNext("d")        }

打印结果:
— PublishSubject example —
Subscription: 1, event: Next(a) —- 订阅者1开始订阅
Subscription: 1, event: Next(b)
Subscription: 1, event: Next(c)
Subscription: 2, event: Next(c) —- 订阅者2开始订阅
Subscription: 1, event: Next(d)
Subscription: 2, event: Next(d)

ReplaySubject

ReplaySubject 在新的订阅出现的时候会补发前几条数据, bufferSize控制着具体补发前边几条数据 , 1就是补发一条, 2就是补发两条, 以此类推

example("ReplaySubject") {            let subject = ReplaySubject<String>.create(bufferSize: 2)            self.writeSequenceToConsole("1", squence: subject)            subject.onNext("a")            subject.onNext("b")            self.writeSequenceToConsole("2", squence: subject)            subject.onNext("c")            subject.onNext("d")        }

打印结果:
— ReplaySubject example —
Subscription: 1, event: Next(a) —- 订阅者1 开始订阅
Subscription: 1, event: Next(b)
Subscription: 2, event: Next(a) —- 订阅者2开始订阅, 并连续收到了订阅前的两组数据
Subscription: 2, event: Next(b)
Subscription: 1, event: Next(c)
Subscription: 2, event: Next(c)
Subscription: 1, event: Next(d)
Subscription: 2, event: Next(d)

BehaviorSubject

BehaviorSubject 在有新的订阅的时候 会发送最近发送的一条数据, 如果最近没有发送则发送默认值

example("BehaviorSubject") {            let subject = BehaviorSubject<String>(value: "z")            self.writeSequenceToConsole("1", squence: subject)            subject.onNext("a")            subject.onNext("b")            self.writeSequenceToConsole("2", squence: subject)            subject.onNext("c")            subject.onCompleted()        }

打印结果:
— BehaviorSubject example —
Subscription: 1, event: Next(z) —-最近没有则发送了默认值”z”
Subscription: 1, event: Next(a)
Subscription: 1, event: Next(b)
Subscription: 2, event: Next(b) —-最近发送的是”b”则在订阅时发送了一条”b”
Subscription: 1, event: Next(c)
Subscription: 2, event: Next(c)
Subscription: 1, event: Completed
Subscription: 2, event: Completed

Variable

variable 类似于 BehaviorSubject 不同之处在于variable不可以主动发送.Completed 和.Error事件, 他会自动判断订阅结束之后发送.Completed事件

example("Variable") {            let variable = Variable("z")            self.writeSequenceToConsole("1", squence: variable.asObservable())            variable.value = "a"            variable.value = "b"            self.writeSequenceToConsole("2", squence: variable.asObservable())            variable.value = "c"        }

打印结果:
— Variable example —
Subscription: 1, event: Next(z)
Subscription: 1, event: Next(a)
Subscription: 1, event: Next(b)
Subscription: 2, event: Next(b)
Subscription: 1, event: Next(c)
Subscription: 2, event: Next(c)
Subscription: 1, event: Completed
Subscription: 2, event: Completed

function

map

map 是对每一个元素进行改变, 相当于把信号内容 更改成其他内容

example("map") {            let originalSequence = Observable.of(1, 2, 3)            _ = originalSequence                .map{$0 * 2} // 对原有数据进行修改                .subscribe{ print($0)}        }

打印结果
— map example —
Next(2)
Next(4)
Next(6)
Completed

FlatMap

Map一般用于对原始的参数进行加工处理,返回值还是基本的类型,可以在subscribe中使用(适用)的类型。
flatMap一般用于输出一个Observable,而其随后的subscribe中的参数也跟Observable中的参数一样,注意不是Observable,一般用于对原始数据返回一个Observable,这个Observable中数据类型可以是原来的,也可以是其他的

example("flatMap") { () -> () in            let sequenceInt = Observable.of(1, 2, 3)            let sequenceString = Observable.of("A", "B", "--")            _ = sequenceInt.flatMap{ (x:Int) -> Observable<String> in                return sequenceString                }.subscribe{                    print($0)            }        }

打印结果
可以看出 flatmap把每一个信号都转换成一个新的Observable
— flatMap example —
Next(A)
Next(B)
Next(–)
Next(A)
Next(B)
Next(–)
Next(A)
Next(B)
Next(–)
Completed

Scan

scan 是遍历源Observable 中的每一个元素 然后根据一定的计算 组合出新的元素 然后把每次计算的结果再发送出来
注意 accumulator的第一个元素为上一次计算的结果

example("scan") { () -> () in            let sequenceToSum = Observable.of(0,1,2,3,4,5)            _ = sequenceToSum.scan(100, accumulator: { a, b in // a为上次组合出来的数据  100 为 首次的数据                a + b            }).subscribe{                print($0)            }        }

打印结果
— scan example —
Next(100)
Next(101)
Next(103)
Next(106)
Next(110)
Next(115)
Completed

Filter

filter 是把通过一定的比较方法 来判断Observable发送的信号是否符合要求, 再把符合要求的发送出去, filter方法的返回值为bool

// 过滤        example("filter") { () -> () in            let subscription = Observable.of(0,1,2,3,4,5,6,7,8,9)            _ = subscription.filter({                $0 % 2 == 0            }).subscribe {                print($0)            }        }

打印结果
— filter example —
Next(0)
Next(2)
Next(4)
Next(6)
Next(8)
Completed

DistinctUntilChanged

distinctUntilChanged 用来过滤掉数据中连续重复的数据
注意是连续重复的!

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

打印结果
— distinctUntilChanged example —
Next(1)
Next(2)
Next(3)
Next(1)
Next(4)
Completed

Take

take 是只把一定量的数据发送出去, 多余的不会发送

 example("take") { () -> () in            let subscription = Observable.of(1, 2, 3, 4, 5, 6)            _ = subscription            // 这里的3 就代表了 只取前三个数据                .take(3)                .subscribe({ (event) -> Void in                    print(event)                })        }

打印结果
— take example —
Next(1)
Next(2)
Next(3)
Completed

Combining

CombineLatest操作符把两个Observable产生的结果进行合并,合并的结果组成一个新的Observable,这两个Observable中任意一个Observable产生的结果,都和另一个Observable最后产生的结果,按照一定的规则进行合并
结果跟多个observable的顺序有关

example("Combining") { () -> () in            let sub1 = Observable.of(1, 2)            let sub2 = Observable.of("a", "b", "c", "d", "e", "f")            let sub3 = Observable.of("!", "@", "#", "$", "^", "&")            _ = Observable.combineLatest(sub1, sub2, sub3) { a, b, c in                "\(a)" + b + c                }.subscribe {                    print($0)            }        }

打印结果
— Combining example —
Next(2f!)
Next(2f@)
Next(2f#)
Next(2f$)
Next(2f^)
Next(2f&)
Completed

StartWith

startwith 可以给一个Observable 在开始时插入一条数据

 example("startWith") {            _ = Observable.of(4, 5, 6, 7, 8, 9)//                .startWith(3)//                .startWith(2)//                .startWith(1)                .startWith(0)                .subscribe {                    print($0)            }        }

打印结果
— startWith example —
Next(0)
Next(4)
Next(5)
Next(6)
Next(7)
Next(8)
Next(9)
Completed

Zip

顾名思义就是压缩的意思
zip会把多个信号(最多8个)进行一对一的, 按顺序组合, 而且必须多个信号都同时有值得时候才可以组合

example("zip") {            let intOb1 = Observable.of(0, 1)            let intOb2 = Observable.of(0, 1, 2, 3)            let intOb3 = Observable.of(0, 1, 2, 3, 4)            _ = Observable.zip(intOb1, intOb2, intOb3) {                ($0 + $1) * $2                }                .subscribe {                    print($0)            }        }

打印结果
可以看出 结果中 只有三组信号中 第0位和第一位的组合, 其余的只要少了一个信号 都不会组合成功
— zip example —
Next(0)
Next(2)
Completed

Merge

merge 和 Combining不同 他是把组合的几组Observable按接收的顺序 一个一个发送出来

example("merge 1") {            let subject1 = PublishSubject<Int>()            let subject2 = PublishSubject<Int>()            _ = Observable.of(subject1, subject2)                .merge()                .subscribeNext { int in                    print(int)            }            subject1.on(.Next(20))            subject1.on(.Next(40))            subject1.on(.Next(60))            subject2.on(.Next(1))            subject1.on(.Next(80))            subject1.on(.Next(100))            subject2.on(.Next(1))        }

打印结果
— merge 1 example —
Next(20)
Next(40)
Next(60)
Next(1)
Next(80)
Next(100)
Next(1)

merge还可以添加一个参数”maxConcurrent” 这个是控制操作的Observable个数

example("merge 2") {            let subject1 = PublishSubject<Int>()            let subject2 = PublishSubject<Int>()            let subject3 = PublishSubject<Int>()            _ = Observable.of(subject1, subject2, subject3)                .merge(maxConcurrent: 2) // 默认 操作个数  2 的意思是 只subject1和subject2                .subscribe {                    print($0)            }            subject1.on(.Next(20))            subject1.on(.Next(40))            subject1.on(.Next(60))            subject2.on(.Next(1))            subject1.on(.Next(80))            subject1.on(.Next(100))            subject2.on(.Next(1))            subject3.on(.Next(12312312))        }

打印结果
— merge 2 example —
Next(20)
Next(40)
Next(60)
Next(1)
Next(80)
Next(100)
Next(1)

SwitchLatest

switchLatest是将一个Observable

example("switchLatest") {            let var1 = Variable(0)            let var2 = Variable(200)            // 这里的var3就是一个Observable<Observable<Int>>            let var3 = Variable(var1.asObservable())            let d = var3                .asObservable()                .switchLatest() // 返回 (self.element as Observable).element  并 只返回最新数据                .subscribe {                    print($0)            }            var1.value = 1            var1.value = 2            var1.value = 3            var1.value = 4// var1的每一次改变 var3都会输出最新结果            // 当var3 的值切换成另一个Observable时也会输出切换后的最新结果            var3.value = var2.asObservable()            var2.value = 201 // 同理改变var1            var1.value = 5            var1.value = 6            var1.value = 7 // 因为var3已经把值切换成了var2 所以var1 的改变 不会影响var3        }

打印结果
— switchLatest example —
Next(0)
Next(1)
Next(2)
Next(3)
Next(4)
Next(200)
Next(201)
Completed

CatchError

catcherror 跟flatmap 有点像 不过 catcherror只能改变出错时的信号 然后进行输出

 example("catchError") { () -> () in            let sequenceThatFails = PublishSubject<Int>()            let recoverySequence = Observable.of(100, 200, 300, 400)            _ = sequenceThatFails            // 当有错误时  对错误进行解析 然后进行正确操作                .catchError({ (error) -> Observable<Int> in                    return recoverySequence                })                // 如果解决错误的方法相对简单 可以用下边的方法直接返回一个默认值                // .catchErrorJustReturn(100)                .subscribe {                    print($0)            }            sequenceThatFails.onNext(1)            sequenceThatFails.onNext(2)            // 发送一个错误            sequenceThatFails.onError(NSError(domain: "错误了", code: 100, userInfo: nil))        }

打印结果
— catchError example —
Next(1)
Next(2)
Next(100)
Next(200)
Next(300)
Next(400)
Completed

Retry

意思就是 在出现错误的时候 通过重新订阅妄图解决错误 -.-!!
不过如果解决不了 就会形成死循环….

example("retry") {            var count = 1 // bad practice, only for example purposes            let funnyLookingSequence = Observable<Int>.create { observer in                let error = NSError(domain: "Test", code: 0, userInfo: nil)                observer.on(.Next(0))                observer.on(.Next(1))                observer.on(.Next(2))                if count < 2 {                    observer.on(.Error(error))                    count += 1                }                observer.on(.Next(3))                observer.on(.Next(4))                observer.on(.Next(5))                observer.on(.Completed)                return NopDisposable.instance            }            _ = funnyLookingSequence                .retry()                .subscribe {                    print($0)            }        }

打印结果
— retry example —
Next(0)
Next(1)
Next(2)
Next(0)
Next(1)
Next(2)
Next(3)
Next(4)
Next(5)
Completed

Subscribe

这个想必你已经了解了 就是订阅, 所有的信号必须通过订阅来进行下一步动作
普通的subscribe 是可以订阅任何类型
有普通就有个别
1, subscribeNext 只订阅next类型事件
2, subscribeCompleted 只订阅complete事件
3, subscribeError 只订阅error事件

这个就不给实例了 上边有的是 ^_^

DoOn

doon是在执行subscript执行之前 插入一条任务,
doon和subscript 有点类似 也有普通形式 和 next, complete , error三种形式

example("doOn") {            let sequenceOfInts = PublishSubject<Int>()            _ = sequenceOfInts                .doOn {                    print("Intercepted event \($0)")                }                .subscribe {                    print($0)            }            sequenceOfInts.on(.Next(1))            sequenceOfInts.on(.Completed)        }

打印结果
— doOn example —
Intercepted event Next(1)
Next(1)
Intercepted event Completed
Completed

Take

take分为takeUntile 和takeWhile
takeUntile 是根据另一条Observable 来终止当前Observable的订阅

 example("takeUntil") {            let originalSequence = PublishSubject<Int>()            let whenThisSendsNextWorldStops = PublishSubject<Int>()            _ = originalSequence                .takeUntil(whenThisSendsNextWorldStops)                .subscribe {                    print($0)            }            originalSequence.on(.Next(1))            originalSequence.on(.Next(2))            originalSequence.on(.Next(3))            originalSequence.on(.Next(4))            whenThisSendsNextWorldStops.on(.Next(1))            originalSequence.on(.Next(5))        }

打印结果
— takeUntil example —
Next(1)
Next(2)
Next(3)
Next(4)
Completed

takeWhile 是根据一个条件来终止当前的OBservable的订阅

 example("takeWhile") {            let sequence = PublishSubject<Int>()            _ = sequence                .takeWhile { int in                    int < 4                }                .subscribe {                    print($0)            }            sequence.on(.Next(1))            sequence.on(.Next(2))            sequence.on(.Next(3))            sequence.on(.Next(4))            sequence.on(.Next(5))        }

打印结果
— takeWhile example —
Next(1)
Next(2)
Next(3)
Completed

Concat

concat 可以合并一系列的信号

example("concat") {            let var1 = BehaviorSubject(value: 0)            let var2 = BehaviorSubject(value: 200)            // var3 is like an Observable<Observable<Int>>            // 把var3的值设置为var1            let var3 = BehaviorSubject(value: var1)            let d = var3                .concat()                .subscribe {                    print($0)            }            var1.on(.Next(1))            var1.on(.Next(2))            var1.on(.Next(3))            var1.on(.Next(4)) // var1改变以后就会使var3的订阅者接收到信息            var3.on(.Next(var2)) // 把var3的值修改为var2            var2.on(.Next(20010)) // 再completed之前 可以改变初始值            var2.on(.Next(2343242))            var1.on(.Next(5))            var1.on(.Next(6))            var1.on(.Next(7))            var1.on(.Completed)            var2.on(.Next(202))            var2.on(.Next(203))            var2.on(.Next(204))        }

打印结果
— concat example —
Next(0) // 订阅的同时就会得到初始值
Next(1)
Next(2)
Next(3)
Next(4)
// 这个时候把var3的值修改为var2
Next(5)
Next(6)
Next(7)// 但在var1没有发送complete之前 var3还是会相应var1的改变
Next(2343242) // 在var1发送了complete之后 var3 立刻收到了 var2的初始值
Next(202)
Next(203)
Next(204)// 以此类推

reduce

类似sacn

example("reduce") {            _ = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)                .reduce(0, accumulator: { (a, b) -> Int in                    print(a)                    return a + b                })                .subscribe {                    print($0)            }        }

打印结果
— reduce example —
0
0
1
3
6
10
15
21
28
36
Next(45)
Completed

总结

到现在 基本的语法 大概就是这些 还有一些 零零散散的 可以在官方的RXplayground中查看,
重点其实是在与运用, 随后我会发一些关于实际应用的文章, 敬请期待…

2 0