RxSwift从零入手 - 介绍
简介
“If you’ve ever used an asynchronous callback based API, you’ve probably dealt with handling the response data ad-hoc all across your codebase, and have most likely decided there was no way to unit test it all… But, let me tell you - there is a better way, and it’s called Rx!”
— Krunoslav Zaher, creator of RxSwift
不可否认,Rx是当今移动应用开发中最热门的话题之一,它是一个多平台的标准,基本上前卫一点的开发者都会有所接触,所以无论是网络开发大会,还是Android,或者Swift研讨会,基本上每次沙龙或者线下面基都会必现他的身影。
对于RxSwift来说,只是其中的一个系列,让你可以使用全新的方式在你敲喜欢的(???)的Swift语言下更容易的编写和测试的优雅代码。
要开发出一个强大高效的应用,肯定就要处理多个并发任务,如播放音频,处理用户界面输入,进行联网调用等等。有时候,将数据从一个进程传递到另一个进程,或者甚至只是观察这些任务以不同的顺序依次发生,仅仅是这些需求,常规处理,就会开发时间直线上升。
本次学习中,我们将会针对RxSwift如何解决与异步编程有关的问题进行讲解,并掌握它,我们从观察简单的数据序列到组合和转换异步流,从而设计架构和构建高质量的应用。
学习成本
- 至少需要安装
OS X El Capitan
系统的Mac。 - 至少安装
Xcode
并且版本需要在8.0
以上。 - 需要对iOS开发有一定的经验(怎么说也得一年以上开发经验吧!!!),
Swift
和UIKit
有较好的理解。 - 本教程不需要开发者账号(2016苹果开放了真机调试权限,Apple ID还是需要的)。
本次学习是针对已经习惯使用
Swift
的iOS开发者,并希望深入研究RxSwift。如果你是一个iOS初学者,建议还是先把Swift和iOS基础夯实了再来进阶。
本次学习会在每个章节都提供了适合对应的项目和源代码,并且涵盖了少量的编程技巧,有些章节设计纯理论,可以自行使用Playground
进行上手。如果读者对于RxSwift有一定的基础了解,不放也阔以先阅读以下前面的基础章节,说不定有啥意想不到的收获。
章节预览
- RxSwift入门:第一部分涵盖了RxSwift基础知识。不要跳过这一节,因为在下面的章节中,我们将需要很好地理解它的工作方式和原理。
- 操作符和最佳实践:在本节中,一旦掌握了基本知识,就可以通过使用操作符来构建更复杂的Rx代码。操作符允许你链接和编写一小部分功能来构建复杂的逻辑。
- iOS应用与RxCocoa:一旦你掌握了RxSwift的基础知识并且知道如何使用操作符,你就可以用RxSwift代码封装现有的iOS类和UI控件。
- 中级RxSwift / RxCocoa:在本节中,我们将谈到更多的话题,比如为应用构建错误处理策略,处理网络需求,响应方式,编写Rx测试等等。
- RxSwift扩展:许多基于RxSwift的可用库都是由社区创建和维护的。在本节中,我们将介绍一些这些项目以及如何在自己的应用中使用它们。
- 融会贯通:这一部你将学习如何构建你的项目,并探索几种不同的方法来设计数据流和项目导航。
Hello RxSwift
RxSwift是什么,RxSwift是一个库,用于通过使用可观察序列和操作符来组合基于事件的异步代码,从而优化函数体的调度参数。
听起来很复杂是吗?Don’t Worry!!!编写响应式程序,需要我们理解其背后的许多概念,以及浏览大量相关的常用术语,这肯定会让人感到恐惧,所谓万事开头难,你自己克服下囖。
本次学习我们会一次介绍各个API及其用法,并在实际的例子和项目中进行实战,让我们可以更好的理解RxSwift的API以及Rx的编程概念。
本次学习是RxSwift主题,奉劝如果脑子里还没有异步的概念,还是就此打住吧,后面内容挺多,你吃不消的。
基础概念
- 状态,可变状态:状态这个词很难定界,各人理解不同,一个通俗的例子就是,比如你的PC,开机的时候都多正常的,Windows跑上三五天,Mac跑上几个月,就会出现很多怪异的问题,装机前辈告知的都是电脑有问题先重启,不行再重装,Windows尽量不要想着修复,耗上三五天只会越修复越奇怪。在软硬件不变的情况下,这里面的问题就是系统状态出了问题,有可能是内存,硬盘或者日志的一些东西导致,尤其是系统状态是多应用之间共享的可变状态。
- 命令式编程:它就和面向过程的C一样,没有方法,只有函数。你只需要把你各自的小功能封装成函数,调用函数执行即可。函数就想命令,比如你让你家的汪,躺下,跳起来一样。。。
比如这样:1
2
3
4
5
6
7override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
setupUI()
connectUIControls()
createDataSource()
listenForChanges()
} - 副作用:涉及到状态这种情况就会有副作用的产,比如有一个全局变量,很多地方都在改变其状态,那就不仅有作用,一定还有很多隐性bug的产生,这里就不多缀诉。
- 声明代码:在命令式编程中,你可以随意更改状态而不会造成任何副作用。RxSwift结合了命令代码和功能代码最好的方面来为你保驾护航。
- 响应式系统:让UI组件根据不同的应用状态保持最新显示。组件基于消息的通信来改进,高可重用性和隔离性,将类的生命周期和实现分开,更易测试。
RxSwift的基础
响应式编程不是一个新概念,它已经存在了相当长的一段时间,但是其核心概念在过去的十年中已经引起了强势回归。
在此期间,Web应用已经变得越来越复杂,并且正面临着管理复杂的异步UI问题。在服务器端,响应式系统已经势在必行。
Rx是微软团队在2009年左右,提供了一个名为Reactive Extensions for .NET(Rx)的新客户端和服务器端框架。
它是.NET 3.5的可安装插件,后来成为.NET 4.0中的一个内置的核心库。自2012年以来,它一直是一个开源组件。开源代码允许其他语言和平台重新实现相同的功能,从而使Rx成为跨平台的标准。
而有今天的RxJS,RxJava,RxKotlin,Rx.NET,RxScala,RxSwift等等。这些库都在努力实现相同的行为和相同的表达API。最终,通过使用RxSwift创建iOS应用的开发也可以在Web上使用RxJS与另一位程序狗自由讨论应用逻辑问题。
和最初的Rx一样,RxSwift也适用于迄今为止所涉及的所有概念:它处理可变状态,它允许编写事件序列并改进体系结构概念,例如代码隔离,可重用性和解耦。
更多关于Rx的问题可以访问他们主页:http://reactivex.io/
废话了一大堆,终于可以进入主题,让我们开始observables
,operators
和schedulers
的学习。
Observables
Observable
是Rx的基础,它是泛型定义Observable<T>
,我们把它理解成一个被观察对象,它所发出的异步数据流是根据泛型T
决定。Observable允许一个或多个观察者订阅,来响应事件进行逻辑并更新UI,或者处理新传入的数据等。Observable
符合ObservableType
协议,它使Observable可以发射(而观察者可以接收)三种类型的事件:
- next事件:此事件会携带最新值以便提供给订阅者使用。
- completed事件:该事件表示成功结束事件序列。这意味着Observable成功完成了它的生命周期,从此不会再发生任何其他事件。
- error事件:Observable携带出错信息终止序列,从此不会再发出其他事件。
异步事件是随着时间推移而转变,比如下面这个可观察的Int类型序列:
又比如这个Int序列有三个观察者,辣么三个观察者都会受到此序列发出的相同的事件:
实际开发中,大致分为两种序列,有限序列和无限序列:
有限的observable序列
它可以发出零个,一个或者多个值,在最后以成功或者错误而终结。
比如iOS开发里常见的文件下载:
- 首先,开始下载并开始观察传入数据。
- 然后在文件的一部分进来时,您重复接收大量的数据。
- 如果网络连接断开,则下载将停止,并且连接将超时且出现错误。
- 或者,下载完所有文件的数据,它将会成功完成。
这个流程描述了一个典型的observable生命周期,代码如下:
1 | API.download(file: "http://www...") |
API.download(file:)
通过返回一个Observable<Data>
实例,因为网络上的数据传输都是二进制数据,所以这里采用Data
类型。
- 在这个下载的例子中,我们通过订阅
onNext事件
,将数据缓存到临时文件夹中。 - 通过订阅
onError事件
在警告框中显示error.localizedDescription或执行其他操作。 - 最后,订阅
onCompleted事件
,在这里可以push一个新的视图控制器来显示下载的文件或者其他内容。
无限的observable序列
说道无限序列,这就会扯到UI事件
了,理想状态下它们是在一个runloop里一直无限循环等待触发。比如设备方向转换,屏幕点击,传感器触发等事件。
让我们看看设备方向的示例:
尽管有的屌毛用户会把设备方向锁死,但是这并不影响事件的无限性。我们来看看下面处理设备方向的逻辑:
1 | UIDevice.rx.orientation |
这里的UIDevice.rx.orientation
是Rx针对UIKit的一个扩展属性,它会提供一个Observable<Orientation>
的可观察序列,我们订阅它并根据当前的方向更新UI。我们完全可以跳过onError
和onCompleted
事件,因为这些事件永远不会从这个可观察的事件中发出。
Operators
Rx同流行的函数式编程一样,提供了很多基础的函数,我们只用关心输入和输出即可,一个数据流输如,输出另一个新的数据流:
1 | UIDevice.rx.orientation |
看代码一脸懵逼是吗?看看流程图:
- 首先,过滤器只允许不是
.landscape
的值通过,如果设备处于横向模式,则订阅的代码将不会被执行,因为过滤器(filter)
已经过滤掉这些事件。 - 在
.portrait
的情况下,我们通过映射器(map)
转换成“竖屏体验最好”的描述。 - 最后我们通过订阅事件流得到一个
String
值用于警告框的内容显示。
filter
和map
只是最基础最基础的操作函数,接下来我们将一步步介绍跟多复杂的操作函数,以便让我们在更复杂的需求里能更得心应手的组合使用。
Schedulers
Schedulers
是Rx的调度器,它是用于任务队列调度。RxSwift附带了许多预定义的调度器,涵盖了99%的用例,所以不到万不得已你还是不要手痒自己去创建。
本次学习前面大部分的示例都是很简单的,通常都是在处理观察数据和更新UI,因此前期不要太过担心调度器的学习成本。这里我们简单的介绍下有个印象就可以了,后面接触到的时候再实地的学习。
我们只需要理解到此图表达的意思就是在以
NSOperation
的自定义调度器上拉取数据,在后台并发调度器上解析数据,最后在主线程调度器上更新UI。
应用架构
这里非常值得一提的就是,我们并不用担心因为引入RxSwift而破坏原本架构,因为我们的Rx只是处理事件和异步数据序列。你可以继续使用MVC架构
,亦或是MVP
,MVVM
都可以,随你喜欢。甚至你还可以选择实现自己的单向数据流架构也都中。
微软的MVVM架构
是专门为在提供数据绑定的平台上创建的事件驱动软件开发的。 RxSwift和MVVM是一对好基友,在本次学习的最后我们会结合两者完成实战,以及如何使用RxSwift来实现它。
MVVM和RxSwift走得很好的原因是,ViewModel
允许你公开Observable<T>
属性,这样你便能使用少量的胶水代码直接在ViewController
中绑定好UIKit空间。这使得绑定模型数据到UI非常简单:
本次学习的大部分示例都会以MVC模式编写,防止引入MVVM带来的学习成本和恐惧,更以便示例代码简单易懂。
RxSwift是Swift版本的Rx的通用实现。因此,它和Cocoa,UIKit两者没有任何关系。
RxCocoa库是RxSwift的小伙伴,它是专门为UIKit和Cocoa开发的库。 除了一些高级类,RxCocoa还为许多UI组件添加响应式扩展,以便您可以订阅各种UI事件。
例如,使用RxCocoa来订阅UISwitch的状态变化非常简单,如下所示:
1 | toggleSwitch.rx.isOn |
我们订阅开关状态以便处理其他逻辑。
类似的还有UITextField, URLSession, UIViewController等等。。。
安装RxSwift
首见官方免费版本:https://github.com/ReactiveX/RxSwift。
作为iOS开发,使用CocoaPods
或者Carthage
随你喜欢,详情参考官方文档即可。