RxSwift

1,396 阅读4分钟

1.函数式编程是种编程范式,他是通过构建函数操作序列,然后对这些序列做出响应的编程方式,它结合了函数式编程以及响应式编程

2.函数式编程的优点

  • 灵活
  • 高复用
  • 简洁
  • 易维护
  • 适应各种需求变化

3.我们通过不同的构建函数,来创建所需要的数据序列。最后通过适当的方式来响应这个序列。这就是函数响应式编程。

4.Observable<Element>是可监听序列,Observe<Element>是观察者,数据绑定(订阅,就是将可监听序列绑定到观察者上。

5.RxSwift核心内容

  • Observable - 产生事件
  • Observer - 响应事件
  • Operator - 创建变化组合事件
  • Disposable - 管理绑定(订阅)的生命周期
  • Schedulers - 线程队列调配

6.Observable - 可监听序列(万物皆序列)

  • Single 发出一个元素,或者一个 error 事件,不会共享附加作用
  • Completable 发出零个元素,发出一个 completed 事件或者一个 error 事件,不会共享附加作用
  • Maybe 发出一个元素或者一个 completed 事件或者一个 error 事件,不会共享附加作用
  • Driver 不会产生 error 事件,一定在 MainScheduler 监听(主线程监听),共享附加作用
  • Signal SignalDriver 相似,唯一的区别是,Driver 会对新观察者回放(重新发送)上一个元素,而 Signal 不会对新观察者回放上一个元素。
  • ControlEvent 不会产生 error 事件,一定在 MainScheduler 订阅(主线程订阅),一定在 MainScheduler 监听(主线程监听)

7,Observer - 观察者是用来监听事件,然后它需要这个事件做出响应,响应事件的都是观察者

  • 创建观察者最直接的方法就是在 Observablesubscribe 方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNextonErroronCompleted的这些闭包构建出来的。
  • Binder 不会处理错误事件,确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler
  • button.rx.isEnabled
extension Reactive where Base: UIControl {
  public var isEnabled: Binder<Bool> {
      return Binder(self.base) { control, value in
          control.isEnabled = value
      }
  }
}
  • label.rx.text
extension Reactive where Base: UILabel {
  public var text: Binder<String?> {
      return Binder(self.base) { label, text in
          label.text = text
      }
  }
}

8.Observable & Observer 既是可监听序列也是观察者,例如:textField的当前文本。它可以看成是由用户输入,而产生的一个文本序列。也可以是由外部文本序列,来控制当前显示内容的观察者:

// 作为可监听序列
let observable = textField.rx.text
observable.subscribe(onNext: { text in show(text: text) })
// 作为观察者
let observer = textField.rx.text
let text: Observable<String?> = ...
text.bind(to: observer)

有许多 UI 控件都存在这种特性,例如:switch的开关状态,segmentedControl的选中索引号,datePicker的选中日期等等。

  • AsyncSubject 将在源 Observable 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),如果源 Observable 没有发出任何元素,只有一个完成事件。那 AsyncSubject 也只有一个完成事件。
let disposeBag = DisposeBag()
let subject = AsyncSubject<String>()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")
subject.onNext("🐹")
subject.onCompleted()

结果

Subscription: 1 Event: next(🐹)
Subscription: 1 Event: completed
  • PublishSubject 将对观察者发送订阅后产生的元素,而在订阅前发出的元素将不会发送给观察者。如果你希望观察者接收到所有的元素,你可以通过使用 Observablecreate 方法来创建 Observable,或者使用 ReplaySubject
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

结果

Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
  • ReplaySubject将对观察者发送全部的元素,无论观察者是何时进行订阅的。

这里存在多个版本的 ReplaySubject,有的只会将最新的 n 个元素发送给观察者,有的只会将限制时间段内最新的元素发送给观察者。

如果把 ReplaySubject 当作观察者来使用,注意不要在多个线程调用 onNext, onErroronCompleted。这样会导致无序调用,将造成意想不到的结果。

let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)//订阅前的缓存个数

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

结果

Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
  • BehaviorSubject 当观察者对 BehaviorSubject 进行订阅时,它会将源 Observable 中最新的元素发送出来(如果不存在最新的元素,就发出默认元素)。然后将随后产生的元素发送出来. (订阅前的最新元素发出来)
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")

subject
  .subscribe { print("Subscription: 1 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🐶")
subject.onNext("🐱")

subject
  .subscribe { print("Subscription: 2 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🅰️")
subject.onNext("🅱️")

subject
  .subscribe { print("Subscription: 3 Event:", $0) }
  .disposed(by: disposeBag)

subject.onNext("🍐")
subject.onNext("🍊")

结果

Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 3 Event: next(🅱️)
Subscription: 1 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 2 Event: next(🍊)
Subscription: 3 Event: next(🍊)
  • ControlProperty 专门用于描述 UI 控件属性的,它具有以下特征: 不会产生 error 事件

一定在 MainScheduler 订阅(主线程订阅 一定在 MainScheduler 监听(主线程监听) 共享附加作用

9,RxSwift 认为不管是 Cold 还是 Hot,它们都是 Observable,它们同属于一个抽象,而不是两种独立的类型。这个观点很有意思,也就是说如果你自己声明了一个 Observable(遵守 ObservableType 协议),使用者并不知道它是 Cold 还是 Hot,只有你自己清楚,真正的“冷暖自知”。

Cold Observable只有在被订阅的时候才会发射事件,每次有新的订阅者都会把之前所有的事件都重新发射一遍; Hot Observable则是实时的,一旦有新的事件它就发射,不管有没有被订阅,而新的订阅者并不会接收到订阅前已经发射过的事件。