版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、大神都在看的RxSwift 的完全入坑手册RxSwift 是我在 Github 上关注已久的一个项目,今天花点时间过了一下它的示例代码,感觉很有意思。我主要是通过项目里的 Rx.playground 进行学习和了解的,这种方式确实便捷高效。只需要把文档用 /*: */ 注释即可,直接用 Markdown 编写,简单方便。不过 Xcode7 中这种方式现在还不是很稳定,会有大量的空行,而且有个最大的问题就是阅读到中间然后切到其他文件再切回来的时候,阅读的进度条是从头开始的,并不能记录上次阅读的位置。心累。下面是我的简单笔记,只是把学习过程中的收获记录下来,大部分内容来自于项目内的 playgro
2、und 。注意!是很大部分!而且操场里图文并茂,很容易理解。所以,各位如果感兴趣,建议 clone 官方项目,跑个操场玩玩。参考文献中罗列了我在学习过程中查阅的相关资料,可以作为补充阅读。SupportCode在进入正题之前,先看下项目里的 SupportCode.swift ,主要为 playground 提供了两个便利函数。一个是 example 函数,专门用来写示例代码的,统一输出 log 便于标记浏览,同时还能保持变量不污染全局: 1. public func example(description: String, action: (
3、) -> () 2. print("n- (description) example -") 3. action() 4. 另一个是 delay 函数,通过 dispatch_after 用来演示延时的: 1. public func delay(delay:Double, closure:()->() 2.
4、160; dispatch_after( 3. dispatch_time( 4. DISPATCH_TIME_NOW, 5. Int64(delay&
5、#160;* Double(NSEC_PER_SEC) 6. ), 7. dispatch_get_main_queue(), closure) 8. Introduction主要介绍了 Rx 的基础: Observable 。 Observable<Element> 是观察者模式中被观察的对象,相当于一个事件序列 (Generat
6、orType) ,会向订阅者发送新产生的事件信息。事件信息分为三种:· .Next(value) 表示新的事件数据。· .Completed 表示事件序列的完结。· .Error 同样表示完结,但是代表异常导致的完结。(打个岔:协议命名,想起来上午汤哥在微博说的一段话:另外,我觉得 protocol 名字用形容词会更加语义分明,比如 Swift : Flyable, Killable, Visible。全用名词的话显得比较生硬,比如 Swift : Head, Wings, Ass。emptyempty 是一个空的序列,它只发送 .Completed 消息。 1.
7、 example("empty") 2. let emptySequence: Observable<Int> = empty() 3. 4. let subscription = emptySequence 5. .subscribe
8、160;event in 6. print(event) 7. 8. 9. 10. - empty example - 11. Completed nevernever 是没有任何元素、也不会发送任何事件的空序列。 1. example(&qu
9、ot;never") 2. let neverSequence: Observable<String> = never() 3. 4. let subscription = neverSequence 5. .subscribe _
10、0;in 6. print("This block is never called.") 7. 8. 9. 10. - never example - justjust 是只包含一个元素的序列,它会先发送
11、 .Next(value) ,然后发送 .Completed 。 1. example("just") 2. let singleElementSequence = just(32) 3. 4. let subscription = singleElementSequence 5. &
12、#160;.subscribe event in 6. print(event) 7. 8. 9. 10. - just example - 11. Next(32) 12. Completed sequence
13、OfsequenceOf 可以把一系列元素转换成事件序列。 1. example("sequenceOf") 2. let sequenceOfElements/* : Observable<Int> */ = sequenceOf(0, 1, 2, 3) 3. 4. let subscription =
14、sequenceOfElements 5. .subscribe event in 6. print(event) 7. 8. 9. 10. - seque
15、nceOf example - 11. Next(0) 12. Next(1) 13. Next(2) 14. Next(3) 15. Completed formform 是通过 asObservable() 方法把 Swift 中的序列 (SequenceType) 转换成事件序列。 1. example("from") 2. let sequenceFromArray = 1, 2
16、, 3, 4, 5.asObservable() 3. 4. let subscription = sequenceFromArray 5. .subscribe event in 6. &
17、#160;print(event) 7. 8. 9. 10. - from example - 11. Next(1) 12. Next(2) 13. Next(3) 14. Next(4) 15. Next(5) 16. Completed createcreate 可以通过闭包创建序列,通过 .on(e: Event) 添加事件。 1. example
18、("create") 2. let myJust = (singleElement: Int) -> Observable<Int> in 3. return create observer in 4.
19、 observer.on(.Next(singleElement) 5. observer.on(.Completed) 6. 7. return NopDisposable.
20、instance 8. 9. 10. 11. let subscription = myJust(5) 12. .subscribe event in 13.
21、 print(event) 14. 15. 16. 17. - create example - 18. Next(5) 19. Completed failWithfailWith 创建一个没有元素的序列,只会发送失败 (.Error) 事件。 1. example("
22、;failWith") 2. let error = NSError(domain: "Test", code: -1, userInfo: nil) 3. 4. let erroredSequence: Observable<Int> = failWith(error) 5.
23、0;6. let subscription = erroredSequence 7. .subscribe event in 8. print(event) 9.
24、0; 10. 11. 12. - failWith example - 13. Error(Error Domain=Test Code=-1 "The operation couldnt be completed. (Test error -1.)") deferreddeferred 会等到有订阅者的时候再通过工厂方法创建 Observable 对象,每
25、个订阅者订阅的对象都是内容相同而完全独立的序列。 1. example("deferred") 2. let deferredSequence: Observable<Int> = deferred 3. print("creating") 4. &
26、#160; return create observer in 5. print("emmiting") 6. observer.on(.Next(0) 7. &
27、#160; observer.on(.Next(1) 8. observer.on(.Next(2) 9. 10. return NopDisposable.instance&
28、#160;11. 12. 13. 14. print("go") 15. 16. deferredSequence 17. .subscribe even
29、t in 18. print(event) 19. 20. 21. deferredSequence 22. .subscribe event in 23.
30、 print(event) 24. 25. 26. 27. - deferred example - 28. go 29. creating 30. emmiting 31. Next(0) 32. Next(1) 33. N
31、ext(2) 34. creating 35. emmiting 36. Next(0) 37. Next(1) 38. Next(2) 为什么需要 defferd 这样一个奇怪的家伙呢?其实这相当于是一种延时加载,因为在添加监听的时候数据未必加载完毕,例如下面这个例子: 1. example("TestDeferred") 2. var value: String? = nil 3.
32、; var subscription: Observable<String?> = just(value) 4. 5. / got value 6. value = "Hello!" 7. 8. subscription.subscribe
33、160;event in 9. print(event) 10. 11. 12. 13. - TestDeferred example - 14. Next(nil) 15. Completed 如果使用 deffered 则可以正常显示想要的数据: 1. example("TestDeferred")
34、60; 2. var value: String? = nil 3. var subscription: Observable<String?> = deferred 4. return just(value) 5.
35、 6. 7. / got value 8. value = "Hello!" 9. 10. subscription.subscribe event in 11. print(event)
36、160;12. 13. 14. 15. 16. - TestDeferred example - 17. Next(Optional("Hello!") 18. Completed Subjects接下来是关于 Subject 的内容。 Subject 可以看做是一种代理和桥梁。它既是订阅者又是订阅源,这意味着它既可以订阅其他 Observable 对象,同时又可以对它的订阅者们发送事件。如果把 Observable 理
37、解成不断输出事件的水管,那 Subject 就是套在上面的水龙头。它既怼着一根不断出水的水管,同时也向外面输送着新鲜水源。如果你直接用水杯接着水管的水,那可能导出来什么王水胶水完全把持不住;如果你在水龙头下面接着水,那你可以随心所欲的调成你想要的水速和水温。(好吧上面一段文档里没有,是我瞎掰的,如果理解错了还望打脸(#)(/)在开始下面的代码之前,先定义一个辅助函数用于输出数据: 1. func writeSequenceToConsole<O: ObservableType>(name: String, sequence: O)&
38、#160; 2. sequence 3. .subscribe e in 4. print("Subscription: (name), event: (e)") 5.
39、0; 6. PublishSubjectPublishSubject 会发送订阅者从订阅之后的事件序列。 1. example("PublishSubject") 2. let subject = PublishSubject<String>() 3. writeSequenceToConsole("1&
40、quot;, sequence: subject) 4. subject.on(.Next("a") 5. subject.on(.Next("b") 6. writeSequenceToConsole("2", sequence: subject) 7. subje
41、ct.on(.Next("c") 8. subject.on(.Next("d") 9. 10. 11. 12. - PublishSubject example - 13. Subscription: 1, event: Next(a) 14. Subscription: 1, event: Next(b) 15. Subscrip
42、tion: 1, event: Next(c) 16. Subscription: 2, event: Next(c) 17. Subscription: 1, event: Next(d) 18. Subscription: 2, event: Next(d) ReplaySubjectReplaySubject 在新的订阅对象订阅的时候会补发所有已经发送过的数据队列, bufferSize 是缓冲区的大小,决定了补发队列的最大值。如
43、果 bufferSize 是1,那么新的订阅者出现的时候就会补发上一个事件,如果是2,则补两个,以此类推。 1. example("ReplaySubject") 2. let subject = ReplaySubject<String>.create(bufferSize: 1) 3. 4. writeSequenceToConsole("1", se
44、quence: subject) 5. subject.on(.Next("a") 6. subject.on(.Next("b") 7. writeSequenceToConsole("2", sequence: subject) 8. subject.on(.Next(&q
45、uot;c") 9. subject.on(.Next("d") 10. 11. 12. - ReplaySubject example - 13. Subscription: 1, event: Next(a) 14. Subscription: 1, event: Next(b) 15. Subscription: 2, event
46、: Next(b) / 补了一个 b 16. Subscription: 1, event: Next(c) 17. Subscription: 2, event: Next(c) 18. Subscription: 1, event: Next(d) 19. Subscription: 2, event: Next(d) BehaviorSubjectBehaviorSubject 在
47、新的订阅对象订阅的时候会发送最近发送的事件,如果没有则发送一个默认值。 1. example("BehaviorSubject") 2. let subject = BehaviorSubject(value: "z") 3. writeSequenceToConsole("1", sequence: subject) 4. &
48、#160; subject.on(.Next("a") 5. subject.on(.Next("b") 6. writeSequenceToConsole("2", sequence: subject) 7. subject.on(.Next("c") 8.
49、0; subject.on(.Completed) 9. 10. 11. - BehaviorSubject example - 12. Subscription: 1, event: Next(z) 13. Subscription: 1, event: Next(a) 14. Subscription: 1, event: Next(b) 15. Subscription: 2,
50、 event: Next(b) 16. Subscription: 1, event: Next(c) 17. Subscription: 2, event: Next(c) 18. Subscription: 1, event: Completed 19. Subscription: 2, event: Completed VariableVariable 是基于 BehaviorSubject 的一层封
51、装,它的优势是:不会被显式终结。即:不会收到 .Completed 和 .Error 这类的终结事件,它会主动在析构的时候发送 .Complete 。e 1. xample("Variable") 2. let variable = Variable("z") 3. writeSequenceToConsole("1", sequence: variable)
52、 4. variable.value = "a" 5. variable.value = "b 6. writeSequenceToConsole("2", sequence: variable) 7. variable.value =
53、"c" 8. 9. 10. - Variable example - 11. Subscription: 1, event: Next(z) 12. Subscription: 1, event: Next(a) 13. Subscription: 1, event: Next(b) 14. Subscription: 2, event: Next(b)
54、 15. Subscription: 1, event: Next(c) 16. Subscription: 2, event: Next(c) 17. Subscription: 1, event: Completed 18. Subscription: 2, event: Completed Transform我们可以对序列做一些转换,类似于 Swift 中 CollectionType 的各种转换。在以前的坑中曾经提到过
55、,可以参考:函数式的函数。mapmap 就是对每个元素都用函数做一次转换,挨个映射一遍。 1. example("map") 2. let originalSequence = sequenceOf(1,2,3) 3. 4. originalSequence 5. .map $0&
56、#160;* 2 6. .subscribe print($0) 7. 8. 9. - map example - 10. Next(2) 11. Next(4) 12. Next(6) 13. Completed flatMapmap 在做转换的时候很容易出现升维的情况,即:转变之后,从一个序列变成了一个序列的序列。什么
57、是升维?在集合中我们可以举这样一个例子,我有一个好友列表 p1, p2, p3,那么如果要获取我好友的好友的列表,可以这样做:myFriends.map $0.getFriends() 结果就成了 p1-1, p1-2, p1-3, p2-1, p3-1, p3-2 ,这就成了好友的好友列表的列表了。这就是一个升维的例子。(以上内容文档中依旧没有,依旧是我瞎掰的,依旧欢迎有错误当面打脸(#)(/)在 Swift 中,我们可以用 flatMap 过滤掉 map 之后的 nil 结果。在 Rx 中, flatMap 可以把一个序列转换成一组序列,然后再把这一组序列拍扁成一个序列。 1. examp
58、le("flatMap") 2. let sequenceInt = sequenceOf(1, 2, 3) 3. let sequenceString = sequenceOf("A", "B", "-") 4. 5.
59、sequenceInt 6. .flatMap int in 7. sequenceString 8. 9.
60、0; .subscribe 10. print($0) 11. 12. 13. 14. - flatMap example - 15. Next(A) 16. Next(B) 17. Next(-) 18. Ne
61、xt(A) 19. Next(B) 20. Next(-) 21. Next(A) 22. Next(B) 23. Next(-) 24. Completed scan 1. scan 有点像 reduce ,它会把每次的运算结果累积起来,作为下一次运算的输入值。 2. 3. example("scan") 4. let sequenceToSum = s
62、equenceOf(0, 1, 2, 3, 4, 5) 5. 6. sequenceToSum 7. .scan(0) acum, elem in 8. acum +&
63、#160;elem 9. 10. .subscribe 11. print($0) 12. 13. &
64、#160;14. 15. - scan example - 16. Next(0) 17. Next(1) 18. Next(3) 19. Next(6) 20. Next(10) 21. Next(15) 22. Completed Filtering除了上面的各种转换,我们还可以对序列进行过滤。filterfilter 只会让符合条件的元素通过。 1. example("filter") 2.
65、0; let subscription = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 3. .filter 4. $0 % 2
66、= 0 5. 6. .subscribe 7. print($0) 8. 9.
67、10. 11. - filter example - 12. Next(0) 13. Next(2) 14. Next(4) 15. Next(6) 16. Next(8) 17. Completed distinctUntilChanged1. distinctUntilChanged 会废弃掉重复的事件。 2. 3. example("distinctUntilChanged") 4.
68、0; let subscription = sequenceOf(1, 2, 3, 1, 1, 4) 5. .distinctUntilChanged() 6. .subscribe 7. &
69、#160; print($0) 8. 9. 10. 11. - distinctUntilChanged example - 12. Next(1) 13. Next(2) 14. Next(3) 15. Next(1) 16. Next(4) 17. Completed taketake 只获取
70、序列中的前 n 个事件,在满足数量之后会自动 .Completed 。 1. example("take") 2. let subscription = sequenceOf(1, 2, 3, 4, 5, 6) 3. .take(3) 4.
71、 .subscribe 5. print($0) 6. 7. 8. 9. - take example - 10. Next(1) 11. Next(2) 12. Next(3) 13. Comple
72、ted Combining这部分是关于序列的运算,可以将多个序列源进行组合拼装成一个新的事件序列。startWith1. startWith 会在队列开始之前插入一个事件元素。 2. 3. example("startWith") 4. let subscription = sequenceOf(4, 5, 6) 5. &
73、#160;.startWith(3) 6. .subscribe 7. print($0) 8. 9. 10. 11. - startWith example
74、0;- 12. Next(3) 13. Next(4) 14. Next(5) 15. Next(6) 16. Completed combineLatest如果存在两条事件队列,需要同时监听,那么每当有新的事件发生的时候,combineLatest 会将每个队列的最新的一个元素进行合并。 1. example("combineLatest 1") 2. let intOb1 = PublishSubje
75、ct<String>() 3. let intOb2 = PublishSubject<Int>() 4. 5. combineLatest(intOb1, intOb2) 6. "($0) ($1)" 7.
76、160; 8. .subscribe 9. print($0) 10. 11. 12. intOb1.
77、on(.Next("A") 13. intOb2.on(.Next(1) 14. intOb1.on(.Next("B") 15. intOb2.on(.Next(2) 16. 17. 18. - combineLatest 1 example - 19. Next(A 1) 20
78、. Next(B 1) 21. Next(B 2) zip1. zip 人如其名,就是压缩两条队列用的,不过它会等到两个队列的元素一一对应地凑齐了之后再合并。 2. 3. example("zip 1") 4. let intOb1 = PublishSubject<String>() 5. let intOb2
79、160;= PublishSubject<Int>() 6. zip(intOb1, intOb2) 7. "($0) ($1)" 8. 9. .s
80、ubscribe 10. print($0) 11. 12. intOb1.on(.Next("A") 13. intOb2.on(.Next(1) 14.
81、; intOb1.on(.Next("B") 15. intOb1.on(.Next("C") 16. intOb2.on(.Next(2) 17. 18. 19. - zip 1 example - 20. Next(A 1) 21. Next(B 2) margemerge 就是 merge
82、 啦,把两个队列按照顺序组合在一起。 1. example("merge 1") 2. let subject1 = PublishSubject<Int>() 3. let subject2 = PublishSubject<Int>() 4. 5. sequenceOf(subjec
83、t1, subject2) 6. .merge() 7. .subscribeNext int in 8. print(int) 9.
84、; 10. 11. subject1.on(.Next(1) 12. subject1.on(.Next(2) 13. subject2.on(.Next(3) 14. subject1.on(.Next(4) 15. subject2.on(.Ne
85、xt(5) 16. 17. 18. - merge 1 example - 19. 1 20. 2 21. 3 22. 4 23. 5 switch当你的事件序列是一个事件序列的序列 (Observable<Observable<T>>) 的时候,(可以理解成二维序列?),可以使用 switch 将序列的序列平铺成一维,并且在出现新的序列的时候,自动切换到最新的那个序列上。和 merge 相似的是,它也是起到了将多个序列拍平成一条序列的作
86、用。 1. example("switchLatest") 2. let var1 = Variable(0) 3. 4. let var2 = Variable(200) 5. 6. / var3 is like an Observable<Obser
87、vable<Int>> 7. let var3 = Variable(var1) 8. 9. let d = var3 10. .switchLatest() 11. .subscr
88、ibe 12. print($0) 13. 14. 15. var1.value = 1 16. var1.value = 2 17.
89、 var1.value = 3 18. var1.value = 4 19. 20. var3.value = var2 21. var2.value = 201 22. var1.value = 5 23. &
90、#160;24. var3.value = var1 25. var2.value = 202 26. var1.value = 6 27. 28. 29. - switchLatest example - 30. Next(0) 31. Next(1) 32. Next(2)
91、160;33. Next(3) 34. Next(4) 35. Next(200) 36. Next(201) 37. Next(5) 38. Next(6) 注意,虽然都是拍平,但是和 flatmap 是不同的, flatmap 是将一条序列变成另一条序列,而这变换过程会让维度变高,所以需要拍平,而 switch 是将本来二维的序列(序列的序列)拍平成了一维的序列。Error Handling在事件序列中,遇到异常也是很正常的事情,有以下几种处理异常的手段。catchErrorcatchError 可以捕获异常事件,并且在后面无缝接
92、上另一段事件序列,丝毫没有异常的痕迹。 1. example("catchError 1") 2. let sequenceThatFails = PublishSubject<Int>() 3. let recoverySequence = sequenceOf(100, 200) 4. 5.
93、160;sequenceThatFails 6. .catchError error in 7. return recoverySequence 8. 9.
94、; .subscribe 10. print($0) 11. 12. 13. sequenceThatFails.on(.Next(1) 14.
95、60; sequenceThatFails.on(.Next(2) 15. sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil) 16. 17. 18. - catchError 1 example - 19. Next(1) 20. Next(2) 21.
96、Next(100) 22. Next(200) 23. Completed retryretry 顾名思义,就是在出现异常的时候会再去从头订阅事件序列,妄图通过从头再来解决异常。 1. example("retry") 2. var count = 1 / bad practice, only for example purposes 3. &
97、#160; let funnyLookingSequence: Observable<Int> = create observer in 4. let error = NSError(domain: "Test", code: 0, userInfo: nil) 5.
98、0; observer.on(.Next(0) 6. observer.on(.Next(1) 7. if count < 2 8.
99、60; observer.on(.Error(error) 9. count+ 10. 11. observer.on(.Next(2) 12.
100、60; observer.on(.Completed) 13. 14. return NopDisposable.instance 15. 16. 17. funnyLookingSequence 18. .ret
101、ry() 19. .subscribe 20. print($0) 21. 22. 23. 24. - retry example - 25. N
102、ext(0) 26. Next(1) 27. Next(0) 28. Next(1) 29. Next(2) 30. Completed Utility这里列举了针对事件序列的一些方法。subscribesubscribe 在前面已经接触过了,有新的事件就会触发。1. example"subscribe") 2. let sequenceOfInts = PublishSubject<Int>()
103、0;3. 4. sequenceOfInts 5. .subscribe 6. print($0) 7. 8. 9.
104、0; sequenceOfInts.on(.Next(1) 10. sequenceOfInts.on(.Completed) 11. 12. 13. - subscribe example - 14. Next(1) 15. Completed 16. 17. subscribeNext 18. 19. subscribeNext 也是订阅,但是只订阅 .Next
105、160;事件。 20. 21. example("subscribeNext") 22. let sequenceOfInts = PublishSubject<Int>() 23. 24. sequenceOfInts 25. .subscribeNext
106、 26. print($0) 27. 28. 29. sequenceOfInts.on(.Next(1) 30. sequenceOfInts.on(.Completed) 31. 32. 33. - subscribeNext example - 34. 1 subscribeCompleted1. subscribeCompleted 是只订阅 .Completed 完成事件。 2.
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 建筑制图课程设计作品
- 卫生间漏水维修协议书
- 化工基础课程设计 大纲
- 立式停车场课程设计
- 皮尔斯振荡器课程设计
- 数字称量勺市场环境与对策分析
- 空气监测课程设计稿
- 氢氧燃烧器项目评价分析报告
- 拆除平房施工方案
- 七年级语文老师在家长会上的发言稿
- 视光中心眼部健康记录册
- 2022江西上饶经济技术开发区招商集团限公司招聘29人上岸笔试历年难、易错点考题附带参考答案与详解
- 大棚钢管下沉施工方案
- CA6140车床控制线路原理详解
- 小学奥数-行程问题三省名师优质课赛课获奖课件市赛课一等奖课件
- 落实立德树人根本任务构建协同育人新格局建设方案
- 高中英语-Natural Disasters教学课件设计
- 郦道元《水经注·序》原文翻译注释与鉴赏
- 高中体育与健康-足球-运球过人教学课件设计
- 北师大版七年级上册生物教学课件 第4章 生物体的结构层次 第1节 细胞分化形成组织
- 对白:文字、舞台、银幕的言语行为艺术
评论
0/150
提交评论