函数响应式式编程(FRP)
函数式编程(FP)
函数式编程就是一种抽象程度很高的编程范式,它将计算机运算看做是数学中函数的计算,而纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用
简单来说: 将函数作为一个单元来处理逻辑,给定一个输入值,就会有对应的一个输出值。函数还可以作为参数和返回值。这就是函数编程。
函数表达式: y = f(x) —> x = f(x) —> y = f(f(x))
函数编程的特性
:
闭包:
一种特殊的函数,绑定了函数内部引用的所有变量,把它引用的东西都放在一个上下文中“包”了起来高阶函数:
把函数作为参数或者返回值的函数匿名函数:
在传入函数时,有些时候,不需要显式地定义函数,可以直接传入匿名函数。柯里化:
把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
优点
:
惰性
递归
响应式编程 (RP)
响应式编程是一种从数据流和变化出发的解决问题的模式。 响应式编程,本质上是对数据流或某种变化所作出的反应,但是这个变化什么时候发生是未知的,所以是基于异步、回调的方式在处理问题。
通俗来讲:A
赋值给B
,B
发生变化的时候A
也会跟着发生变化,这就是响应式编程。
响应式编程
:
数据流:
一个流就是一串事件发生的时间的值的序列。这里面至少有三要素:数据
、报错
、完成
.变化:
信号变化回调
函数响应式编程(FRP)
函数响应式编程:说白了就是函数式和响应式的结合.
RxSwift 介绍
RxSwift:
是 Rx 为 Swift 语言开发的一门函数响应式编程语言, 它可以代替iOS系统的 Target Action / 代理 / 闭包 / 通知 / KVO,同时还提供网络、数据绑定、UI事件处理、UI的展示和更新、多线程……
在RxSwift中,所有异步操作(事件)和数据流均被抽象为可观察序列的概念
RxSwift的主要流程: 创建序列 --> 订阅序列 --> 发送信号 --> 信号接收
一、RxSwift 配置
- 使用RxSwift需要导入
RxSwift
、RxCocoa
这两个库,缺一不可。这两个库的主要作用是:
RxSwift:
它只是基于 Swift 语言的Rx
标准实现接口库,所以RxSwift
里不包含任何Cocoa
或者UI
方面的类RxCocoa:
是基于RxSwift
针对于iOS
开发的一个库,它通过Extension
的方法给原生的比如UI 控件
添加了Rx
的特性,使得我们更容易订阅和响应这些控件的事件。
- 再使用
RxSwift
的地方import
这个两个库就行
import RxSwift
import RxCocoa
二、Observable (创建、订阅、销毁)
1、Observable
Observable<T>:
观察序列
1、Observable 这个类就是 Rx 框架的基础,我们可以称它为可观察序列。它的作用就是可以异步地产生一系列的 Event(事件),即一个 Observable 对象会随着时间推移不定期地发出 event(element : T) 这样一个东西。
2、这些 Event 还可以携带数据,它的泛型 就是用来指定这个 Event 携带的数据的类型。
3、有了可观察序列,我们还需要有一个 Observer(订阅者)来订阅它,这样这个订阅者才能收到 Observable 不时发出的 Event。
Enevt:
事件。
Observable
可以发出三种不同的事件:next
、error
、completed
public enum Event<Element> {
/// Next element is produced.
case next(Element)
/// Sequence terminated with an error.
case error(Swift.Error)
/// Sequence completed successfully.
case completed
}
1、
next
:next
事件就是那个可以携带数据 <T>
的事件
2、error:
error
事件表示一个错误,它可以携带具体的错误内容,一旦 Observable 发出了 error event,则这个 Observable 就等于终止了,以后它再也不会发出 event 事件了
3、completed
:completed
事件表示Observable
发出的事件正常地结束了,一旦Observable
发出了completed event
,则这个Observable
就等于终止了,以后它再也不会发出event
事件了
2、Observable 序列的创建
Observable
有好多种序列的创建方法,我们这里就解说一种比较常用的create() 序列
创建,其他常见的可以参考Observable 常见的序列创建方法
create 序列
- 该方法接受一个 闭包形式的参数,任务是对每一个过来的订阅进行处理。
- 下面是一个简单的样例。为方便演示,这里增加了订阅相关代码
- 这也是序列创建的一般方式,应用非常之多
// 1、创建序列
_ = Observable<String>.create({ (observable) -> Disposable in
//3、发送信号
observable.onNext("RxSwift 你好!")
// observable.onError() //发送错误信号
// observable.onCompleted() //发送完成信号
return Disposables.create() // 销毁
// 2、订阅序列
}).subscribe(onNext: { (next) in
NSLog("订阅到--\(next)")
}, onError: { (error) in
NSLog("错误--\(error)")
}, onCompleted: {
NSLog("完成回调")
}, onDisposed: {
NSLog("订释放回调")
})
3、Observable 订阅
一般我们创建完Observable
序列以后,我们会用subscribe()
对其进行订阅,用来接收Observable
发出的事件Event
.
关于subscribe
的订阅有两种方式:
subscribe()
方法:该方法的 block 的回调参数就是被发出的 event 事件,我们将其直接打印出来。
let observable = Observable<String>.of("Json","XML")
observable.subscribe { (event) in
Log("---of----\(event)")
}.disposed(by: self.disposeBag)
// 打印值
//ofQueue():73->---of----next(Json)
//ofQueue():73->---of----next(XML)
//ofQueue():73->---of----completed
1、初始化
Observable
序列时设置的默认值都按顺序
通过.next
事件发送出来
2、next
事件送完以后,还会自动发送一个completed
事件
3、我们要向获取接收到的元素可以用event.element
去获取
subscribe
的另一种订阅方法:该方法可以把event
进行分类,通过不同的block
回调处理不同类型的event
,同时会把event
携带的数据
直接解包出来作为参数,方便我们使用。
let observable = Observable<String>.of("Json","XML")
observable.subscribe { (element) in
print("---of----\(element)")
} onError: { (error) in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}
// 打印
//---of----Json
//---of----XML
//completed
//disposed
1、我们通过打印发现这次直接打印的是
element
,不需要event.element
处理了
2、每个回调都独立出来了,我们可以做一些不同的业务需求
4、监听事件的生命周期
关于事件的生命周期,我们可以用doOn
来监听,关于doOn
:
doOn
方法的调用不会影响subscribe
的调用doOn
方法会在每一次事件发送前被调用- 同时它和
subscribe
一样,可以通过不同的block
回调处理不同类型的event
doOn
的每个回调都发生在subscribe
之前
do(onNext:)
方法在subscribe(onNext:)
前调用
do(onCompleted:)
方法在subscribe(onCompleted:)
前面调用
do(onDisposed)
销毁方法却是在subscribe(onDisposed)
后面调用的
let observable = Observable<String>.of("Json","XML")
observable
.do(onNext: { element in
print("---do---\(element)" )
}, onError: { error in
print("do Error:", error)
}, onCompleted: {
print("do Completed")
}, onDispose: {
print("do Disposed")
})
.subscribe { (element) in
print("---of---\(element)")
} onError: { (error) in
print(error)
} onCompleted: {
print("completed")
} onDisposed: {
print("disposed")
}
打印
// ---do---Json
// ---of---Json
// ---do---XML
// ---of---XML
// do Completed
// completed
//disposed
// do Disposed
5、Observable 的销毁(Dispose)
当一个Observable
被观察订阅后,就会产生一个Disposable
实例,通过这个实例,我们就能进行资源的释放了。
对于RxSwift
中资源的释放,也就是解除绑定、释放空间,有两种方法,分别是显式释放
和隐式释放
显式释放
: 也就是dispose()
, 可以让我们在代码中直接调用释放方法进行资源的释放
let dispose = self.TestButton.rx.tap.subscribe({ _ in
NSLog("点击")
})
dispose.dispose()
隐式释放
隐式释放
则通过DisposeBag
来进行,它类似于Objective-C ARC
中的自动释放池机制.
DisposeBag
对于RxSwift
就像自动释放池一样,我们把资源添加到DisposeBag
中,让资源随着DisposeBag
一起释放。
DisposeBag
就像个垃圾袋一样,我们把创建的序列
放在DisposeBag
这个垃圾袋中,他会在合适的时候帮我们释放资源。
// 可以写成全局的
static var disposeBag = DisposeBag()
let observable = Observable<String>.of("Json","XML")
observable
.subscribe { (event) in
Log("---of----\(event)")
}.disposed(by: self.disposeBag)