26408376f0abf05f0e8f2fb6b92dfad9
跟我学RxSwift05 - 观察者(上): AnyObserver、Binder

一、Observer - 观察者

观察者 是用来监听事件,然后它需要这个事件做出响应。例如:弹出提示框就是观察者,它对点击按钮这个事件做出响应。

响应事件的都是观察者
在第三小节 Observable 介绍及使用 中,我们举了个几个例子来介绍什么是可被监听的序列。那么我们还是用这几个例子来解释一下什么是观察者

  • 当室温高于 33 度时,打开空调降温 打开空调降温就是观察者 Observer<Double>

</>

  • 当《火影忍者》更新一集时,我们就立即观看这一集 观看这一集就是观察者 Observer<OnePieceEpisode>

</>

  • 当取到 JSON 时,将它打印出来 将它打印出来就是观察者 Observer<JSON>

</>

  • 当任务结束后,提示用户任务已完成 提示用户任务已完成就是观察者 Observer<Void>

二、创建观察者

创建观察者最直接的方法就是在 Observablesubscribe 方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNextonErroronCompleted的这些闭包构建出来的。

let observable = Observable.of("A", "B", "C")

observable.subscribe(onNext: { element in
    print(element)
}, onError: { error in
    print(error)
}, onCompleted: {
    print("completed")
})

// 运行结果:
A
B
C
completed

以上是创建观察者最常见的方法。当然你还可以通过其他的方式来创建观察者, 即我们今天的主角:AnyObserverBinder

三、使用 AnyObserver 创建观察者

AnyObserver 可以用来描叙任意一种观察者

  • 配合 subscribe 方法使用 打印网络请求结果:
URLSession.shared.rx.data(request: URLRequest(url: url))
    .subscribe(onNext: { data in
        print("Data Task Success with count: \(data.count)")
    }, onError: { error in
        print("Data Task Error: \(error)")
    })
    .disposed(by: disposeBag)

可以看作是:

let observer: AnyObserver<Data> = AnyObserver { (event) in
    switch event {
    case .next(let data):
        print("Data Task Success with count: \(data.count)")
    case .error(let error):
        print("Data Task Error: \(error)")
    default:
        break
    }
}

URLSession.shared.rx.data(request: URLRequest(url: url))
    .subscribe(observer)
    .disposed(by: disposeBag)

<hr>

  • 配合 bindTo 方法使用 用户名提示语是否隐藏:
usernameValid
    .bind(to: usernameValidOutlet.rx.isHidden)
    .disposed(by: disposeBag)

可以看作是:

let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
    switch event {
    case .next(let isHidden):
        self?.usernameValidOutlet.isHidden = isHidden
    default:
        break
    }
}

usernameValid
    .bind(to: observer)
    .disposed(by: disposeBag)

</>

四、使用 Binder 创建观察者

Binder 主要有以下两个特征:

  • 不会处理错误事件
  • 确保绑定都是在给定 Scheduler 上执行(默认 MainScheduler

一旦产生错误事件,在调试环境下将执行 fatalError,在发布环境下将打印错误信息。
<hr>

示例

在介绍 AnyObserver 时,我们举了这样一个例子:

let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
    switch event {
    case .next(let isHidden):
        self?.usernameValidOutlet.isHidden = isHidden
    default:
        break
    }
}

usernameValid
    .bind(to: observer)
    .disposed(by: disposeBag)

由于这个观察者是一个 UI 观察者,所以它在响应事件时,只会处理 next 事件,并且更新 UI 的操作需要在主线程上执行。

因此一个更好的方案就是使用 Binder:

let observer: Binder<Bool> = Binder(usernameValidOutlet) { (view, isHidden) in
    view.isHidden = isHidden
}

usernameValid
    .bind(to: observer)
    .disposed(by: disposeBag)

Binder 可以只处理 next 事件,并且保证响应 next 事件的代码一定会在给定 Scheduler 上执行,这里采用默认的 MainScheduler
<hr>

复用

由于页面是否隐藏是一个常用的观察者,所以应该让所有的 UIView 都提供这种观察者

extension Reactive where Base: UIView {
  public var isHidden: Binder<Bool> {
      return Binder(self.base) { view, hidden in
          view.isHidden = hidden
      }
  }
}
usernameValid
    .bind(to: usernameValidOutlet.rx.isHidden)
    .disposed(by: disposeBag)

这样你不必为每个 UI 控件单独创建该观察者。这就是 usernameValidOutlet.rx.isHidden 的由来,许多 UI 观察者 都是这样创建的:

  • 按钮是否可点击 button.rx.isEnabled:
extension Reactive where Base: UIControl {
  public var isEnabled: Binder<Bool> {
      return Binder(self.base) { control, value in
          control.isEnabled = value
      }
  }
}
  • label 的当前文本 label.rx.text:
extension Reactive where Base: UILabel {
  public var text: Binder<String?> {
      return Binder(self.base) { label, text in
          label.text = text
      }
  }
}

你也可以用这种方式来创建自定义的 UI 观察者

OK,今天的内容就到此为止,祝大家学习愉快。 每天进步一点点,加油!!!
下节预告:跟我学RxSwift06 - 观察者(下):自定义可绑定属性

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