基础
RxSwift简介
-
复合
-
复用
-
清晰:声明不可变更
-
易用:抽象了异步编程
-
稳定
函数响应式编程
函数式编程
-
函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础也是lamda运算,而且lamda运算的函数可以接受函数当作输入(参数)和输出(返回值)
-
和指令式编程,函数响应式编程强调函数的计算比指令的执行更重要
-
和过程化编程,函数响应式编程里函数的计算可以随时调用
响应式编程
-
一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动将变化的值通过数据流进行传播。
-
数据流:只能以事先规定好的顺序被覆去一次的数据的一个序列
-
变化传播:类似观察者模式,变化了要通知别人
对比
我们有一个数组let arr = [0,1,2,3,4,5]。需求:1. 获取所有>=3的数字。2. 所有的数字+1 。3. 打印所有偶数。
-
常规写法
var newArr1:[Int] = []
for item in arr {
guard item >= 3,
(item + 1) % 2 == 0 else {
continue
}
newArr1.append(item)
}
可以看出来可读性不强,且乍一看不是很能从代码中看出需求。
-
函数式编程
var newArr2:[Int] = []
arr.filter{ $0 >= 3 }
.filter{ ($0 + 1) % 2 == 0 }
.forEach{ newArr2.append($0) }
是不是清晰明了!
KVO
前面已经可以看出函数式编程的好处,那么问题来了,假如我们有一个变量var a = 10,且希望另一个变量为a的两倍var b = a * 2,此时肯定是能得出b为20,但是如果a变化,b是不会跟着变化的,这就需要我们的KVO机制。
/*
注:
1. 需要添加观察者的对象类型必须继承自NSObject
2. 需要被观察的属性必须加上@objc和dynamic
*/
class DemoObject : NSObject{
@objc dynamic var name: String = "Letty"
var age: Int = 24
}
var obj: DemoObject = DemoObject()
// 添加观察者
self.addObserver(self.obj,
forKeyPath: "name",
options: .new,
context: nil)
// KVO回调
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
guard keyPath == "name" else {
return
}
print(change as Any)
}
// 注:deinit需要移除观察者
deinit {
self.obj.removeObserver(self,
forKeyPath: "name")
}
当值发生变化

可以监听到变化。
思考
有没有觉得这样其实也很不方便?添加观察者的地方和处理逻辑需要分开写。且如果要观察的对象一多就很容易混淆。这就要引出我们的RxSwift。
RxSwift
上述情况的RxSwift写法,可以看出你需要对值的变化的任何处理都可以放在同一个地方,是不是清晰明白了很多!!
// 类似一个垃圾袋,回收资源时一个一个回收,就不需要我们手动回收了
let disposeBag = DisposeBag()
// 添加到响应序列DisposeBag中
self.obj.rx.observeWeakly(String.self,
"name")
.subscribe(onNext: { value in
print(value as Any)
}, onError: { error in
print(error.localizedDescription)
}, onCompleted: {
print("onCompleted")
}, onDisposed: {
print("onDisposed")
})
.disposed(by: disposeBag)
Observable可观察序列
-
类似sequence,
next即为任务链 -
无穷序列
// 不断订阅
let ob = Observable<Element>.interval({RxTimeInterval},
<SchedulerType>)
-
有穷序列
let ob = Observable.just([1,2,3])
ob.subscribe { num in
print(num)
} onCompleted: {
print("订阅完成")
}
核心逻辑
重点步骤
-
创建序列
let yk_observable = Observable<Any>.create { (observer) -> Disposable in
// 3. 发送信号
observer.onNext("发送值!")
observer.onError(NSError(domain: "YKERROR",
code: 404,
userInfo: nil))
return Disposables.create()
}
-
订阅信号
let yk_disposable = yk_observable.subscribe { anyElement in
// 订阅到值
print("订阅到值:\\(anyElement)")
} onError: { error in
// 错误
print(error)
} onCompleted: {
// 完成
print("onCompleted")
} onDisposed: {
// 销毁
print("onDisposed")
}
-
发送信号(在创建序列的闭包中处理)。也就是说,在创建序列的闭包中传入的操作,都会分别触发第二步中观察者的操作。
observer.onNext("发送值!")
observer.onError(NSError(domain: "YKERROR",
code: 404,
userInfo: nil))
return Disposables.create()
observer.onNext("发送值!")
observer.onError(NSError(domain: "YKERROR",
code: 404,
userInfo: nil))
return Disposables.create()
流程探索
-
我们从
create方法入手,可以看到该方法会创建一个AnonymousObservable类型的对象,并保存传入的【何时/如何调用onNext/onError等方法】的闭包。
/ *
- parameter subscribe: 得到的可观察序列的subscribe方法的实现
- returns:Observable类型,为传入的subscribe闭包指定实现的可观察序列。
*/
public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable)
-> Observable<Element> {
// 创建了一个匿名内部类AnonymousObservable 继承自Producer
AnonymousObservable(subscribe)
}
AnonymousObservable在初始化时,保存了subscribe闭包为属性【记录操作】,也就是将create方法传入的 (AnyObserver<Element>) -> Disposable)存储下来。
init(_ subscribeHandler: @escaping SubscribeHandler) {
self.subscribeHandler = subscribeHandler
}
-
流程第二步:
subscribe探索。第一步返回的是Observable,在其父类ObservableType的扩展方法中【ObservableType+Extensions.swift】可以找到上述订阅信号的方法实现。
/**
向可观察序列订阅元素处理程序、错误处理程序、完成处理程序和处置处理程序。
- parameter onNext: 可观察序列中的每个元素调用的操作
- parameter onError: 在可观察序列错误终止时调用的操作
- parameter onCompleted: 可观察序列优雅终止时调用的动作。
- parameter onDisposed: 在任何类型的序列终止时调用的操作(完成/错误/取消订阅)
- returns: Disposable类型。订阅对象,用于取消对可观察序列的订阅。
*/
public func subscribe(
onNext: ((Element) -> Void)? = nil,
onError: ((Swift.Error) -> Void)? = nil,
onCompleted: (() -> Void)? = nil,
onDisposed: (() -> Void)? = nil
) -> Disposable {
在方法实现中,会创建一个Disposables订阅者类型的对象,并保存传入的【当捕获到值/error/事件完成的消息时要做什么处理】的闭包。
// 1. 创建Disposable对象,传入【事件处理的闭包】,创建了一个内部的AnonymousObserver
let observer = AnonymousObserver<Element> { event in
···
}
// 2. 创建Disposables对象,传入的两个参数分别是【将自身添加到观察者序列】【第一步中保存了操作的Disposable对象】
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
忍不住疑惑
self.asObservable().subscribe(observer)
这一步做了什么。进入源码可以看出:self即为第一步中我们创建的AnonymousObservable对象,其调用asObservable()方法返回的是自身,而在subscribe方法中我们也可以根据断点来看

在当前线程调用自身的run方法。
func run(_ parent: Parent) -> Disposable {
parent.subscribeHandler(AnyObserver(self))
}
到这里就很清晰了,如果看晕了的话我们可以通过lldb来看一下这是什么。

也就是说会调用我们在第一步中创建的AnonymousObservable对象保存的闭包中的代码。根据调用堆栈也可以清晰的看出。
