大神都在看的RxSwift的完全入坑手册.docx_第1页
大神都在看的RxSwift的完全入坑手册.docx_第2页
大神都在看的RxSwift的完全入坑手册.docx_第3页
大神都在看的RxSwift的完全入坑手册.docx_第4页
大神都在看的RxSwift的完全入坑手册.docx_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

网址:edu.51CTO.com大神都在看的RxSwift 的完全入坑手册RxSwift是我在 Github 上关注已久的一个项目,今天花点时间过了一下它的示例代码,感觉很有意思。我主要是通过项目里的Rx.playground进行学习和了解的,这种方式确实便捷高效。只需要把文档用/*: */注释即可,直接用 Markdown 编写,简单方便。不过 Xcode7 中这种方式现在还不是很稳定,会有大量的空行,而且有个最大的问题就是阅读到中间然后切到其他文件再切回来的时候,阅读的进度条是从头开始的,并不能记录上次阅读的位置。心累。下面是我的简单笔记,只是把学习过程中的收获记录下来,大部分内容来自于项目内的 playground 。注意!是很大部分!而且操场里图文并茂,很容易理解。所以,各位如果感兴趣,建议 clone 官方项目,跑个操场玩玩。参考文献中罗列了我在学习过程中查阅的相关资料,可以作为补充阅读。SupportCode在进入正题之前,先看下项目里的SupportCode.swift,主要为 playground 提供了两个便利函数。一个是example函数,专门用来写示例代码的,统一输出 log 便于标记浏览,同时还能保持变量不污染全局:1. publicfuncexample(description:String,action:()-()2. print(n-(description)example-)3. action()4. 另一个是delay函数,通过dispatch_after用来演示延时的:1. publicfuncdelay(delay:Double,closure:()-()2. dispatch_after(3. dispatch_time(4. DISPATCH_TIME_NOW,5. Int64(delay*Double(NSEC_PER_SEC)6. ),7. dispatch_get_main_queue(),closure)8. Introduction主要介绍了 Rx 的基础:Observable。Observable是观察者模式中被观察的对象,相当于一个事件序列 (GeneratorType) ,会向订阅者发送新产生的事件信息。事件信息分为三种: .Next(value)表示新的事件数据。 .Completed表示事件序列的完结。 .Error同样表示完结,但是代表异常导致的完结。(打个岔:协议命名,想起来上午汤哥在微博说的一段话:另外,我觉得 protocol 名字用形容词会更加语义分明,比如 Swift : Flyable, Killable, Visible。全用名词的话显得比较生硬,比如 Swift : Head, Wings, Ass。emptyempty是一个空的序列,它只发送.Completed消息。1. example(empty)2. letemptySequence:Observable=empty()3. 4. letsubscription=emptySequence5. .subscribeeventin6. print(event)7. 8. 9. 10. -emptyexample-11. Completednevernever是没有任何元素、也不会发送任何事件的空序列。1. example(never)2. letneverSequence:Observable=never()3. 4. letsubscription=neverSequence5. .subscribe_in6. print(Thisblockisnevercalled.)7. 8. 9. 10. -neverexample-justjust是只包含一个元素的序列,它会先发送.Next(value),然后发送.Completed。1. example(just)2. letsingleElementSequence=just(32)3. 4. letsubscription=singleElementSequence5. .subscribeeventin6. print(event)7. 8. 9. 10. -justexample-11. Next(32)12. CompletedsequenceOfsequenceOf可以把一系列元素转换成事件序列。 1. example(sequenceOf)2. letsequenceOfElements/*:Observable*/=sequenceOf(0,1,2,3)3. 4. letsubscription=sequenceOfElements5. .subscribeeventin6. print(event)7. 8. 9. 10. -sequenceOfexample-11. Next(0)12. Next(1)13. Next(2)14. Next(3)15. Completedformform是通过asObservable()方法把 Swift 中的序列 (SequenceType) 转换成事件序列。1. example(from)2. letsequenceFromArray=1,2,3,4,5.asObservable()3. 4. letsubscription=sequenceFromArray5. .subscribeeventin6. print(event)7. 8. 9. 10. -fromexample-11. Next(1)12. Next(2)13. Next(3)14. Next(4)15. Next(5)16. Completedcreatecreate可以通过闭包创建序列,通过.on(e: Event)添加事件。1. example(create)2. letmyJust=(singleElement:Int)-Observablein3. returncreateobserverin4. observer.on(.Next(singleElement)5. observer.on(.Completed)6. 7. returnNopDisposable.instance8. 9. 10. 11. letsubscription=myJust(5)12. .subscribeeventin13. print(event)14. 15. 16. 17. -createexample-18. Next(5)19. CompletedfailWithfailWith创建一个没有元素的序列,只会发送失败 (.Error) 事件。1. example(failWith)2. leterror=NSError(domain:Test,code:-1,userInfo:nil)3. 4. leterroredSequence:Observable=failWith(error)5. 6. letsubscription=erroredSequence7. .subscribeeventin8. print(event)9. 10. 11. 12. -failWithexample-13. Error(ErrorDomain=TestCode=-1Theoperationcouldntbecompleted.(Testerror-1.)deferreddeferred会等到有订阅者的时候再通过工厂方法创建Observable对象,每个订阅者订阅的对象都是内容相同而完全独立的序列。1. example(deferred)2. letdeferredSequence:Observable=deferred3. print(creating)4. returncreateobserverin5. print(emmiting)6. observer.on(.Next(0)7. observer.on(.Next(1)8. observer.on(.Next(2)9. 10. returnNopDisposable.instance11. 12. 13. 14. print(go)15. 16. deferredSequence17. .subscribeeventin18. print(event)19. 20. 21. deferredSequence22. .subscribeeventin23. print(event)24. 25. 26. 27. -deferredexample-28. go29. creating30. emmiting31. Next(0)32. Next(1)33. Next(2)34. creating35. emmiting36. Next(0)37. Next(1)38. Next(2)为什么需要defferd这样一个奇怪的家伙呢?其实这相当于是一种延时加载,因为在添加监听的时候数据未必加载完毕,例如下面这个例子:1. example(TestDeferred)2. varvalue:String?=nil3. varsubscription:Observable=just(value)4. 5. /gotvalue6. value=Hello!7. 8. subscription.subscribeeventin9. print(event)10. 11. 12. 13. -TestDeferredexample-14. Next(nil)15. Completed如果使用deffered则可以正常显示想要的数据:1. example(TestDeferred)2. varvalue:String?=nil3. varsubscription:Observable=deferred4. returnjust(value)5. 6. 7. /gotvalue8. value=Hello!9. 10. subscription.subscribeeventin11. print(event)12. 13. 14. 15. 16. -TestDeferredexample-17. Next(Optional(Hello!)18. CompletedSubjects接下来是关于Subject的内容。Subject可以看做是一种代理和桥梁。它既是订阅者又是订阅源,这意味着它既可以订阅其他Observable对象,同时又可以对它的订阅者们发送事件。如果把Observable理解成不断输出事件的水管,那Subject就是套在上面的水龙头。它既怼着一根不断出水的水管,同时也向外面输送着新鲜水源。如果你直接用水杯接着水管的水,那可能导出来什么王水胶水完全把持不住;如果你在水龙头下面接着水,那你可以随心所欲的调成你想要的水速和水温。(好吧上面一段文档里没有,是我瞎掰的,如果理解错了还望打脸(#)(/)在开始下面的代码之前,先定义一个辅助函数用于输出数据:1. funcwriteSequenceToConsole(name:String,sequence:O)2. sequence3. .subscribeein4. print(Subscription:(name),event:(e)5. 6. PublishSubjectPublishSubject会发送订阅者从订阅之后的事件序列。1. example(PublishSubject)2. letsubject=PublishSubject()3. writeSequenceToConsole(1,sequence:subject)4. subject.on(.Next(a)5. subject.on(.Next(b)6. writeSequenceToConsole(2,sequence:subject)7. subject.on(.Next(c)8. subject.on(.Next(d)9. 10. 11. 12. -PublishSubjectexample-13. Subscription:1,event:Next(a)14. Subscription:1,event:Next(b)15. Subscription:1,event:Next(c)16. Subscription:2,event:Next(c)17. Subscription:1,event:Next(d)18. Subscription:2,event:Next(d)ReplaySubjectReplaySubject在新的订阅对象订阅的时候会补发所有已经发送过的数据队列,bufferSize是缓冲区的大小,决定了补发队列的最大值。如果bufferSize是1,那么新的订阅者出现的时候就会补发上一个事件,如果是2,则补两个,以此类推。1. example(ReplaySubject)2. letsubject=ReplaySubject.create(bufferSize:1)3. 4. writeSequenceToConsole(1,sequence:subject)5. subject.on(.Next(a)6. subject.on(.Next(b)7. writeSequenceToConsole(2,sequence:subject)8. subject.on(.Next(c)9. subject.on(.Next(d)10. 11. 12. -ReplaySubjectexample-13. Subscription:1,event:Next(a)14. Subscription:1,event:Next(b)15. Subscription:2,event:Next(b)/补了一个b16. Subscription:1,event:Next(c)17. Subscription:2,event:Next(c)18. Subscription:1,event:Next(d)19. Subscription:2,event:Next(d)BehaviorSubjectBehaviorSubject在新的订阅对象订阅的时候会发送最近发送的事件,如果没有则发送一个默认值。1. example(BehaviorSubject)2. letsubject=BehaviorSubject(value:z)3. writeSequenceToConsole(1,sequence:subject)4. subject.on(.Next(a)5. subject.on(.Next(b)6. writeSequenceToConsole(2,sequence:subject)7. subject.on(.Next(c)8. subject.on(.Completed)9. 10. 11. -BehaviorSubjectexample-12. Subscription:1,event:Next(z)13. Subscription:1,event:Next(a)14. Subscription:1,event:Next(b)15. Subscription:2,event:Next(b)16. Subscription:1,event:Next(c)17. Subscription:2,event:Next(c)18. Subscription:1,event:Completed19. Subscription:2,event:CompletedVariableVariable是基于BehaviorSubject的一层封装,它的优势是:不会被显式终结。即:不会收到.Completed和.Error这类的终结事件,它会主动在析构的时候发送.Complete。e 1. xample(Variable)2. letvariable=Variable(z)3. writeSequenceToConsole(1,sequence:variable)4. variable.value=a5. variable.value=b6. writeSequenceToConsole(2,sequence:variable)7. variable.value=c8. 9. 10. -Variableexample-11. Subscription:1,event:Next(z)12. Subscription:1,event:Next(a)13. Subscription:1,event:Next(b)14. Subscription:2,event:Next(b)15. Subscription:1,event:Next(c)16. Subscription:2,event:Next(c)17. Subscription:1,event:Completed18. Subscription:2,event:CompletedTransform我们可以对序列做一些转换,类似于 Swift 中CollectionType的各种转换。在以前的坑中曾经提到过,可以参考:函数式的函数。mapmap就是对每个元素都用函数做一次转换,挨个映射一遍。1. example(map)2. letoriginalSequence=sequenceOf(1,2,3)3. 4. originalSequence5. .map$0*26. .subscribeprint($0)7. 8. 9. -mapexample-10. Next(2)11. Next(4)12. Next(6)13. CompletedflatMapmap在做转换的时候很容易出现升维的情况,即:转变之后,从一个序列变成了一个序列的序列。什么是升维?在集合中我们可以举这样一个例子,我有一个好友列表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. example(flatMap)2. letsequenceInt=sequenceOf(1,2,3)3. letsequenceString=sequenceOf(A,B,-)4. 5. sequenceInt6. .flatMapintin7. sequenceString8. 9. .subscribe10. print($0)11. 12. 13. 14. -flatMapexample-15. Next(A)16. Next(B)17. Next(-)18. Next(A)19. Next(B)20. Next(-)21. Next(A)22. Next(B)23. Next(-)24. Completedscan1. scan有点像reduce,它会把每次的运算结果累积起来,作为下一次运算的输入值。2. 3. example(scan)4. letsequenceToSum=sequenceOf(0,1,2,3,4,5)5. 6. sequenceToSum7. .scan(0)acum,elemin8. acum+elem9. 10. .subscribe11. print($0)12. 13. 14. 15. -scanexample-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. letsubscription=sequenceOf(0,1,2,3,4,5,6,7,8,9)3. .filter4. $0%2=05. 6. .subscribe7. print($0)8. 9. 10. 11. -filterexample-12. Next(0)13. Next(2)14. Next(4)15. Next(6)16. Next(8)17. CompleteddistinctUntilChanged1. distinctUntilChanged会废弃掉重复的事件。2. 3. example(distinctUntilChanged)4. letsubscription=sequenceOf(1,2,3,1,1,4)5. .distinctUntilChanged()6. .subscribe7. print($0)8. 9. 10. 11. -distinctUntilChangedexample-12. Next(1)13. Next(2)14. Next(3)15. Next(1)16. Next(4)17. Completed taketake只获取序列中的前 n 个事件,在满足数量之后会自动.Completed。1. example(take)2. letsubscription=sequenceOf(1,2,3,4,5,6)3. .take(3)4. .subscribe5. print($0)6. 7. 8. 9. -takeexample-10. Next(1)11. Next(2)12. Next(3)13. CompletedCombining这部分是关于序列的运算,可以将多个序列源进行组合拼装成一个新的事件序列。startWith1. startWith会在队列开始之前插入一个事件元素。2. 3. example(startWith)4. letsubscription=sequenceOf(4,5,6)5. .startWith(3)6. .subscribe7. print($0)8. 9. 10. 11. -startWithexample-12. Next(3)13. Next(4)14. Next(5)15. Next(6)16. Completed combineLatest如果存在两条事件队列,需要同时监听,那么每当有新的事件发生的时候,combineLatest会将每个队列的最新的一个元素进行合并。 1. example(combineLatest1)2. letintOb1=PublishSubject()3. letintOb2=PublishSubject()4. 5. combineLatest(intOb1,intOb2)6. ($0)($1)7. 8. .subscribe9. print($0)10. 11. 12. intOb1.on(.Next(A)13. intOb2.on(.Next(1)14. intOb1.on(.Next(B)15. intOb2.on(.Next(2)16. 17. 18. -combineLatest1example-19. Next(A1)20. Next(B1)21. Next(B2)zip1. zip人如其名,就是压缩两条队列用的,不过它会等到两个队列的元素一一对应地凑齐了之后再合并。2. 3. example(zip1)4. letintOb1=PublishSubject()5. letintOb2=PublishSubject()6. zip(intOb1,intOb2)7. ($0)($1)8. 9. .subscribe10. print($0)11. 12. intOb1.on(.Next(A)13. intOb2.on(.Next(1)14. intOb1.on(.Next(B)15. intOb1.on(.Next(C)16. intOb2.on(.Next(2)17. 18. 19. -zip1example-20. Next(A1)21. Next(B2) margemerge就是 merge 啦,把两个队列按照顺序组合在一起。1. example(merge1)2. letsubject1=PublishSubject()3. letsubject2=PublishSubject()4. 5. sequenceOf(subject1,subject2)6. .merge()7. .subscribeNextintin8. print(int)9. 10. 11. subject1.on(.Next(1)12. subject1.on(.Next(2)13. subject2.on(.Next(3)14. subject1.on(.Next(4)15. subject2.on(.Next(5)16. 17. 18. -merge1example-19. 120. 221. 322. 423. 5switch当你的事件序列是一个事件序列的序列 (ObservableObservable) 的时候,(可以理解成二维序列?),可以使用switch将序列的序列平铺成一维,并且在出现新的序列的时候,自动切换到最新的那个序列上。和merge相似的是,它也是起到了将多个序列拍平成一条序列的作用。1. example(switchLatest)2. letvar1=Variable(0)3. 4. letvar2=Variable(200)5. 6. /var3islikeanObservableObservable7. letvar3=Variable(var1)8. 9. letd=var310. .switchLatest()11. .subscribe12. print($0)13. 14. 15. var1.value=116. var1.value=217. var1.value=318. var1.value=419. 20. var3.value=var221. var2.value=20122. var1.value=523. 24. var3.value=var125. var2.value=20226. var1.value=627. 28. 29. -switchLatestexample-30. Next(0)31. Next(1)32. Next(2)33. Next(3)34. Next(4)35. Next(200)36. Next(201)37. Next(5)38. Next(6)注意,虽然都是拍平,但是和flatmap是不同的,flatmap是将一条序列变成另一条序列,而这变换过程会让维度变高,所以需要拍平,而switch是将本来二维的序列(序列的序列)拍平成了一维的序列。Error Handling在事件序列中,遇到异常也是很正常的事情,有以下几种处理异常的手段。catchErrorcatchError可以捕获异常事件,并且在后面无缝接上另一段事件序列,丝毫没有异常的痕迹。1. example(catchError1)2. letsequenceThatFails=PublishSubject()3. letrecoverySequence=sequenceOf(100,200)4. 5. sequenceThatFails6. .catchErrorerrorin7. returnrecoverySequence8. 9. .subscribe10. print($0)11. 12. 13. sequenceThatFails.on(.Next(1)14. sequenceThatFails.on(.Next(2)15. sequenceThatFails.on(.Error(NSError(domain:Test,code:0,userInfo:nil)16. 17. 18. -catchError1example-19. Next(1)20. Next(2)21. Next(100)22. Next(200)23. Completedretryretry顾名思义,就是在出现异常的时候会再去从头订阅事件序列,妄图通过从头再来解决异常。1. example(retry)2. varcount=1/badpractice,onlyforexamplepurposes3. letfunnyLookingSequence:Observable=createobserverin4. leterror=NSError(domain:Test,code:0,userInfo:nil)5. observer.on(.Next(0)6. observer.on(.Next(1)7. ifcount28. observer.on(.Error(error)9. count+10. 11. observer.on(.Next(2)12. observer.on(.Completed)13. 14. returnNopDisposable.instance15. 16. 17. funnyLookingSequence18. .retry()19. .subscribe20. print($0)21. 22. 23. 24. -retryexample-25. Next(0)26. Next(1)27. Next(0)28. Next(1)29. Next(2)30. CompletedUtility这里列举了针对事件序列的一些方法。subscribesubscribe在前面已经接触过了,有新的事件就会触发。1. examplesubscribe)2. letsequenceOfInts=PublishSubject()3. 4. sequenceOfInts5. .subscribe6. print($0)7. 8. 9. sequenceOfInts.on(.Next(1)10. sequenceOfInts.on(.Completed)11. 12. 13. -subscribeexample-14. Next(1)15. Completed16. 17. subscribeNext18. 19. subscribeNext也是订阅,但是只订阅.Next事件。20. 21. example(subscribeNext)22. letsequenceOfInts=PublishSubject()23. 24. sequenceOfInts25. .subscribeNext26. print($0)27. 28. 29. sequenceOfInts.on(.Next(1)30. sequenceOfInts.on(.Co

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论