RxSwift核心之Observer

作者: __Mr_Xie__ | 来源:发表于2019-10-09 11:01 被阅读0次

简介

观察者 (Observer) 的作用就是监听事件,然后对这个事件做出响应,或者说任何响应事件的行为都是观察者。比如:

  • 当前视频播放到30分钟时,弹出视频小剧场(广告),后者就是 观察者
  • 当前温度高于30度,打开空调降温,后者就是 观察者
  • 当你点击视频拍摄时,系统弹出弹框问你是否同意使用摄像头,后者就是 观察者
  • ······

eg:

tap.subscribe(onNext: { [weak self] in
    self?.showAlert()
}, onError: { error in
    print("发生错误: \(error.localizedDescription)")
}, onCompleted: {
    print("任务完成")
})

在这里,弹出提示框就是 观察者
创建观察者最直接的方法就是在 Observablesubscribe 方法后面描述,事件发生时,需要如何做出响应。而观察者就是由后面的 onNextonErroronCompleted 的这些闭包构建出来的。此外,我们还有AnyObserverBinder 方式创建观察者。

AnyObserver

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

  • 打印网络请求结果
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)
  • 打印网络请求结果
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

基本介绍
1、相较于 AnyObserver 的大而全,Binder 更专注于特定的场景。Binder 主要有以下两个特征:

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

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

eg:

import RxSwift
import RxCocoa
 
@IBOutlet weak var lable: UILabel!

func test() {
        let disposeBag = DisposeBag()
        
        // 观察者
        let observer: AnyObserver<String> = AnyObserver { [weak self] (event) in
            switch event {
            case .next(let text):
                // 收到发出的索引数后显示到label上
                self?.lable.text = text
            default:
                break
            }
        }
         
        // Observable序列(just:创建一个序列,只包含一个元素)
        let observable = Observable<Int>.just(100)
        observable.map { (index) -> String in
            return "当前索引数:\(index)"
        }.observeOn(MainScheduler.instance).bind(to: observer).disposed(by: disposeBag)
    }

在上面示例代码中,label 标签的文字显示就是一个典型的 UI 观察者。它在响应事件时,只会处理 next 事件,而且更新 UI 的操作需要在主线程上执行。那么这种情况下更好的方案就是使用 Binder,代码如下:

import RxSwift
import RxCocoa
 
@IBOutlet weak var lable: UILabel!

func test() {
        let disposeBag = DisposeBag()
        
        // 观察者
        let observer: Binder<String> = Binder(lable) { (view, text) in
            // 收到发出的索引数后显示到label上
            view.text = text
        }
             
        // Observable序列(just:创建一个序列,只包含一个元素)
        let observable = Observable<Int>.just(100)
        observable.map { (index) -> String in
            return "当前索引数:\(index)"
            }.observeOn(MainScheduler.instance).bind(to: observer).disposed(by: disposeBag)
     }

附:BinderRxCocoa 中的应用
1、其实 RxCocoa 在对许多 UI 控件进行扩展时,就利用 Binder 将控件属性变成观查者,比如 UIControl+Rx.swift 中的 isEnabled 属性便是一个 observer

import RxSwift
import UIKit
 
extension Reactive where Base: UIControl {
     
    // Bindable sink for `enabled` property.
    public var isEnabled: Binder<Bool> {
        return Binder(self.base) { control, value in
            control.isEnabled = value
        }
    }
}

2、因此我们可以将序列直接绑定到它上面。比如下面样例,就可以用来判断 button 可用 / 不可用

@IBOutlet weak var button: UIButton!

@IBAction func buttonClick(_ sender: UIButton) {
        print("点击了按钮")
    }

func test() {
        let disposeBag = DisposeBag()
        
        let observable = Observable<Int>.just(100)
        
        observable.map { (e) -> Bool in
            return (e != 100)
            }.observeOn(MainScheduler.instance).bind(to: button.rx.isEnabled).disposed(by: disposeBag)
    }

Author

如果你有什么建议,可以关注我的公众号:iOS开发者进阶,直接留言,留言必回。

相关文章

网友评论

    本文标题:RxSwift核心之Observer

    本文链接:https://www.haomeiwen.com/subject/kyibpctx.html