RxSwift 是在 Apple 推出 Swift 后,针对 Swift 语言 ReactiveX 推出 Reactive Extensions 系列一个实现库;除此之外,ReactiveX 还推出了 RxJava,RxAndroid,RxPHP 等蕴含类似思想的框架。
为什么要学习RxSwift
我们知道 C 语言的面向过程,Objective-C、C++ 面向对象编程, Java 的 Spring 框架提出了面向切面编程的思想,学习 RxSwift 不是学习如何使用第三方库,而是学习一种编程思想--函数响应式编程;另外,RxSwift是ReactiveX提出的,其他语言的Rx项目在编程思想上也是一致的,因此如果我们学会了如何使用RxSwift,再去学习Rx.Net, RxJava 或者 RxJS就是小菜一碟,只是语言语法上的差异。这真的就是learn once, apply everywhere.
RxSwift的优点
Composable 可组合,在设计模式中有一种模式叫做组合模式,你可以方便的用不同的组合实现不同的类
Reusable 代码可重用,原因很简单,对应RxSwift,就是一堆Obserable
Declarative 响应式的,因为状态不可变,只有数据变化 Understandable and concise 简洁,容易理解。
Stable 稳定,因为RxSwift写出的代码,单元测试时分方便
Less stateful “无”状态性,因为对于响应式编程,你的应用程序就是一堆数据流
Without leaks 没有泄漏,因为资源管理非常简单
RxSwift实践
1、通过pods引入RxSwift和RxCocoa三方库
RxSwift 是 Swift 语言的函数响应式编程框架。 RxCocoa 则是对苹果原声面向对象 Api 的封装。
pod 'RxSwift'
pod 'RxCocoa'
需要用到 RxSwift 相关内容的类里面,引入模块即可。
import RxSwift
import RxCocoa
2、RxSwift的简单应用
监听UITextField的输入,并把输入的文字展示在UILabel上
(1) 传统做法
成为文本框的代理
textField1.delegate = self
textField2.delegate = self
实现文本框协议
// MARK: - UITextFieldDelegate
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// 判断是哪一个输入框发生改变
if textField == textField1 {
print("输入框1 改变")
} else {
print("输入框2 改变")
}
return true
}
}
这样做可能面临的问题:界面有多个文本框,需要每个都实现代理,并且需要判断是哪一个文本框发生了改变,维护成本比较高,代码可读性差。
(2) RxSwift做法
首先订阅 UITextField,文字输入改变时通过闭包回调,进行打印
TF1.rx.text .subscribe { (str: Event<String?>) in
print(str)
}.addDisposableTo(bag)
把UITextField文字改变的Obserable与UILabel文字改变的Obserale进行绑定
TF1.rx.text .bindTo(label.rx.text).addDisposableTo(bag)
(3) 效果图
3、使用RxSwift重写车务通项目中事件提醒列表
tips:在开始之前请确认安装了RxDataSources这个三方库,如果没有这个库,会崩溃至死。
RxDataSources是使用RxSwift对UITableView和UICollectionView的数据源做了一层包装,引入方法与见步骤1
(1) 为UITableView中的每一个Cell的数据基本结构封装数据模型 RXTestSectionModel包含两个参数,headerName为section的名字,items为这个section中所包含的item数组
struct RXTestItemModel {
let licensePlate: String
let eventType: String
let eventTime: String
let isDeal: String
}
//其实这个可以写成 SectionModel<String, RXTestItemModel> ,但是可读性不好,因此在这个的基础上封装一下sectionModel
struct RXTestSectionModel {
let headerName: String
var items: [Item]
}
extension RXTestSectionModel: SectionModelType {
typealias Item = RXTestItemModel
init(original: RXTestSectionModel, items: [Item]) {
self = original
self.items = items
}
}
(2)在视图控制器中声明dataSource属性
let dataSource = RxTableViewSectionedReloadDataSource<RXTestSectionModel>()
//(3) 自定义UITableViewCell UI的相关代码在这里略去,在Cell中定义一个item数据模型的变量
var innerItemModel: RXTestItemModel?
var itemModel: RXTestItemModel? {
set {
innerItemModel = newValue
licensePlateLb.text = innerItemModel?.licensePlate
alarmNameLb.text = innerItemModel?.eventType
alarmTimeLb.text = innerItemModel?.eventTime
if innerItemModel?.isDeal == "1" {
dealStatusImageView.image = UIImage.init(named: "chuli_icon")
} else {
dealStatusImageView.image = UIImage.init(named: "weichuli_icon")
}
}
get {
return innerItemModel
}
}
(4) 配置Cell
dataSource.configureCell = {
(_, tableView: UITableView, indexPath: IndexPath, eventItemModel: RXTestItemModel) in
let cell = tableView.dequeueReusableCell(withIdentifier: RXTestTableViewCell.CellIdentify(), for: indexPath) as! RXTestTableViewCell
cell.tag = indexPath.row
cell.itemModel = eventItemModel
return cell
}
(5) 从接口请求数据并复制给一个[RXTestSectionModel] () 类型的Variable 在这里,itemsList作为一个桥梁,因为普通数据类型无法被当做被观察对象,因此,我们用itemsList.value来接收数据,在把它与tableView的dataSouce进行数据绑定。
//TIP: Variable 中的类型必须是 实例化的数组 要不然在 itemsList.asObservable().bindTo(innertableview.rx.items(dataSource: dataSource)) .addDisposableTo(bag) 绑定中会有错误
var itemsList: Variable = Variable([RXTestSectionModel]())
dataprovider.cwtRxQueryAlarmListWith(targetLicensePlate: "", targetTypeId: "1", pageNo: 0, pageSize: 10).subscribe(onNext: { sectionModel in
self.cmcciotStopLoading()
print(sectionModel)
self.itemsList.value = [sectionModel]
}, onError: {
errorInfo inself.cmcciotStopLoading()
}).addDisposableTo(bag)
itemsList.asObservable().bindTo(innertableview.rx.items(dataSource: dataSource)) .addDisposableTo(bag)
(6)最终效果图
在RxSwift使用和学习的过程中了解到RxSwift语法更加简洁,使用了更少的中间变量和更少的代码,之前8-9句代码RxSwift几乎1句就可以搞定,但是在代码简洁的同时也发现,其代码可读性不高。如果有任何问题,还请各位大神及时指正。