Af8d0837bc09cc769162a6727635ec96
跟我学RxSwift07 - Observable & Observer 既是可被监听的序列也是观察者(Subjects、Variables)

我们上节内容讲了 观察者 的使用方法:怎样自定义可绑定属性。本节内容我们讲?大家在看到标题后是不是有一点懵呢?

其实我们环顾一下前面的几篇文章就会发现:当我们创建一个 Observable 的时候就要预先将要发出的数据都准备好,等到有人订阅它时再将数据通过 Event 发出去。

但有时我们希望 Observable 在运行时能动态地“获得”或者说“产生”出一个新的数据,再通过 Event 发送出去。

例如: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 的选中日期等等。

RXSwift框架里面已经为我们定义了一些辅助类型,它们既是可被监听的序列也是观察者。如果你能合适的应用这些辅助类型,它们就可以帮助你更准确的描述事物的特征:


<a id="1">AsyncSubject</a>

AsyncSubject
AsyncSubject 将在源 Observable 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),如果源 Observable没有发出任何元素,只有一个完成事件。那 AsyncSubject 也只有一个完成事件。

AsyncSubject1
它会对随后的观察者发出最终元素。如果源 Observable 因为产生了一个 error 事件而中止, AsyncSubject 就不会发出任何元素,而是将这个 error 事件发送出来。

例:

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

<a id="2">PublishSubject</a>

PublishSubject
PublishSubject 将对观察者发送订阅后产生的元素,而在订阅前发出的元素将不会发送给观察者。如果你希望观察者接收到所有的元素,你可以通过使用 Observablecreate 方法来创建 Observable,或者使用 ReplaySubject

PublishSubject1

如果源 Observable 因为产生了一个 error 事件而中止, PublishSubject 就不会发出任何元素,而是将这个 error 事件发送出来。
例:

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(🅱)

<a id="3">ReplaySubject</a>

ReplaySubject
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(🅱)

<a id="4">BehaviorSubject</a>

BehaviorSubject
当观察者对 BehaviorSubject 进行订阅时,它会将源 Observable 中最新的元素发送出来(如果不存在最新的元素,就发出默认元素)。然后将随后产生的元素发送出来。

BehaviorSubject1
如果源 Observable 因为产生了一个 error 事件而中止, BehaviorSubject 就不会发出任何元素,而是将这个 error 事件发送出来。

例:

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(🍊)

<a id="5">Variable</a>

Swift 中我们经常会用 var 关键字来声明变量。RxSwift 提供的 Variable 实际上是 varRx 版本,你可以将它看作是 RxVar
我们来对比一下 var 以及 Variable 的用法:

使用 var:

// 在 ViewController 中
var model: Model? = nil {
    didSet { updateUI(with: model) }
}

override func viewDidLoad() {
    super.viewDidLoad()

    model = getModel()
}

func updateUI(with model: Model?) { ... }
func getModel() -> Model { ... }

使用 Variable:

// 在 ViewController 中
let model: Variable<Model?> = Variable(nil)

override func viewDidLoad() {
    super.viewDidLoad()

    model.asObservable()
        .subscribe(onNext: { [weak self] model in
            self?.updateUI(with: model)
        })
        .disposed(by: disposeBag)

    model.value = getModel()
}

func updateUI(with model: Model?) { ... }
func getModel() -> Model { ... }

第一种使用 var 的方式十分常见,在 ViewController 中监听 Model 的变化,然后刷新页面。

第二种使用 Variable 则是 RxSwift 独有的。Variable 几乎提供了 var 的所有功能。另外,加上一条非常重要的特性,就是可以通过调用 asObservable() 方法转换成序列。然后你可以对这个序列应用操作符,来合成其他的序列。所以,如果我们声明的变量需要提供 Rx 支持,那就选用 Variable 这个类型。

说明
Variable 封装了一个BehaviorSubject,所以它会持有当前值,并且 Variable 会对新的观察者发送当前值。它不会产生 error 事件。Variabledeinit 时,会发出一个 completed 事件。


<a id="6">ControlProperty</a>

ControlProperty 专门用于描述 UI 控件属性的,它具有以下特征:

  • 不会产生 error 事件
  • 一定在 MainScheduler 订阅(主线程订阅)
  • 一定在 MainScheduler 监听(主线程监听)
  • 共享状态变化

OK,今天的内容就到此为止,祝大家学习愉快。 每天进步一点点,加油!!!
下节预告:跟我学RxSwift08 - Operator : 操作符

© 著作权归作者所有
这个作品真棒,我要支持一下!
RxSwift系列教程, 从多个方面逐一介绍RxSwift的使用方法,不仅会介绍RxSwift的核心内容: 1. ...
0条评论
top Created with Sketch.