作为一个iOS开发人员, 当
Swift
遇上了RxSwift
--> 函数响应式编程,在没有认识RxSwift
之前,可能是一脸的懵逼,即使偶尔使用一下也是丈二的和尚莫不着头脑,胡乱使用,但是当你认识了解并深入探索以后,你会对RxSwift
爱不释手,甚至忘记最初代码的写法!!!!
函数响应式编程
1. 函数式 :
-
函数式编程
不是一种技术,而是一种高级抽象的编程思想设计,简称FP(Functional Programming)
,函数
一词就直观的体现了这就是一个数学运算方法。它又分为两种形式:
- 无副作用:函数没有变量,这种纯粹的函数式编程语言,一旦输入确定,那么输出就是确定的,它是没有副作用的。
- 有副作用:函数有变量,这种函数式编程语言它的输入会随着变量不断的变化,最后的输出也就不确定,它是存在副作用的。
函数表达式 :
y = f(x) ---> x = f(x) ---> y = f(f(x))
废话不多说,直接实例感受一把:
/**
1. 首先获取 > 3的数字
2. 获取的数字之后 + 1
3.所有数字中的偶数
*/
let array = [1,2,3,4,5,6,7,8,9,10]
for num in array{
if num > 3{
let number = num + 1
if (number % 2 == 0) {
print(number)
}
}
}
/**
以上代码看起来没有任何问题,确实也毛病,但是:
* 上面的代码嵌套层次之深,让人感觉非常恶心
* 代码的可读性也是非常差的
* 代码复用性较低
* 维护以及代码构建成本太高
*/
//这样就成了函数式出现的必要性:
array.filter{ $0 > 3}
.filter{ ($0+1) % 2 == 0 }
.forEach { print($0) }
/**
* 代码层次非常清晰
* 代码可读性高
* 代码复用性高
* 代码简洁,直接面向开发需求
*/
2. 响应式 :
-
响应式编程
是一种基于异步数据流概念的编程模式。数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。响应式编程的一个关键概念是事件。事件可以被等待,可以触发过程,也可以触发其它事件 - 而iOS原生开发中,触发对象与响应方法是分离的,如
button
的初始化和点击响应方法是分离的。类似的还有tap
、textField
、textView
、notifaction
、KVO
、NSTimer
等等。
RxSwift来源
RxSwift
是 Rx家族 的重要一员,Rx
就是复合的代名词, 不仅仅是一种使用可观察数据流进行异步编程的接口,他更是一种编程思想理念的突破实践。它集结了多种编程模式和精华于一身,包括:观察者模式,迭代器,函数响应式编程等待。 RxSwift
作为Rx
家族的一员,一样继承了Rx
的这一系列的特性。
RxSwift优势
-
RxSwift
是Swift
函数响应式编程的一个开源库:github地址, 其目的就是让可观察数据流、异步编程能够更好序列化,使用swift
进行函数响应式编程。 - 它拓展了观察者模式,使你能够自由组合多个异步事件,而不需要去
关心线程
,同步
,线程安全
,并发数据以及I/O阻塞
。 -
RxSwift
是Rx
为Swift
语言开发的一门函数响应式编程语言, 它可以代替iOS系统的Target Action
,代理
,闭包
,通知
,KVO
,同时还提供网络
,数据绑定
,UI事件处理
,UI的展示和更新
,多线程
……
RxSwift学习必要性
- 复合 - Rx 就是和复合的代名词
- 复⽤用 - 复⽤用性⽐比较强 - 代码量量降低
- 清晰 - 因为声明都是不不可变更更,代码函数式编程可读性强
- 易易⽤用 - 理理解容易易,还抽象的了了异步编程,统⼀代码⻛风格
- 稳定 - 因为 Rx 是完全通过单元测试的
RxSwift初识
1.KVO
//MARK: - KVO-原始三部曲
//1.添加观察者
self.person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
//2.实现观察者方法
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
print("响应")
print(change as Any)
}
//3.移除观察者
deinit {
self.person.removeObserver(self, forKeyPath: "name")
}
//MARK: - RxSwift应用-KVO
func setupKVO() {
self.person.rx.observeWeakly(String.self, "name")
.subscribe(onNext: { (value) in
print(value as Any)
})
.disposed(by: disposeBag)
}
2.UI层
- UIButton
//MARK: - button原始是写法
self.button.addTarget(self, action: #selector(click), for: .touchUpInside)
func click() {
print("点击")
}
//MARK: - RxSwift应用-button响应
func setupButton() {
self.button.rx.tap
.subscribe(onNext: { () in
print("点击来了")
})
.disposed(by: disposeBag)
//上面的代码和下面的意思一样
self.button.rx.controlEvent(.touchUpInside)
.subscribe(onNext: { () in
print("点击了")
})
.disposed(by: disposeBag)
}
- UITextFiled
//MARK: - RxSwift应用-textfiled
func setupTextFiled() {
// 我们如果要对输入的文本进行操作 - 比如输入的的内容 然后我们获取里面的偶数
// self.textFiled.delegate = self
// 感觉是不是特别恶心
// 下面我们来看看Rx
self.textFiled.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
print("监听到了 - \(text)")
}).disposed(by: disposeBag)
self.textFiled.rx.text.bind(to: self.button.rx.title()).disposed(by: disposeBag)
}
- UIScrollView
//MARK: - RxSwift应用-scrollView
func setupScrollerView() {
scrollView.rx.contentOffset
.subscribe(onNext: { [weak self](content) in
self?.view.backgroundColor = UIColor.init(red: content.y/255*0.8, green: content.y/255*0.6, blue: content.y/255*0.3, alpha: 1)
})
.disposed(by: disposeBag)
}
- Tap手持
//MARK: - 手势
func setupGestureRecognizer(){
let tap = UITapGestureRecognizer()
self.label.addGestureRecognizer(tap)
self.label.isUserInteractionEnabled = true
tap.rx.event.subscribe(onNext: { (tap) in
print(tap.view)
})
.disposed(by: disposeBag)
}
3.通知
//MARK: - 通知
func setupNotification(){
NotificationCenter.default.rx
.notification(UIResponder.keyboardWillShowNotification)
.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
}
4.NSTimer
//MARK: - RxSwift应用-timer定时器
func setupTimer() {
timer = Observable.interval(1, scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print("hello word \(num)")
}).disposed(by: disposeBag)
}
5.网络
//MARK: - RxSwift应用-网络请求
func setupNextwork() {
let url = URL(string: "https://www.baidu.com")
URLSession.shared.rx.response(request: URLRequest(url: url!))
.subscribe(onNext: { (response, data) in
print("response ==== \(response)")
print("data ===== \(data)")
}, onError: { (error) in
print("error ===== \(error)")
}).disposed(by: disposeBag)
}
Rx 以前:
- KVO三部曲很恶心,不直观
- UI层 需要设置
代理
或者addTarget
,代码逻辑与事件逻辑分层- 通知的实现,也是比较友善的:编程习惯都有在RxSwift风格里面保留,降低了开发门槛
- 手势看是去还是很不爽,还是需要添加到视图上,可扩展一层再次处理,这样就好了
- Timer根据创建受RunLoop影响,还要手动销毁,还可能有线程问题
Rx 以后:
RxSwift
温柔的一句代码搞定,腰也不疼了,腿也不酸了,一口气直接上6楼,timer还不受RunLoop影响了,也不用手动管理了,线程这些也都安全了
总结
- 简单的
rx
体验,就能让人感觉,真的是处处皆rx
,而且清晰简洁,分段式操作,函数式响应。对比原始写法,一个字爽~把函数响应式玩到了高潮!无论从代码量,还是从代码的可读性,抑或代码的复用性......都是大大优化!