RxSwift学习一

响应式编程(Reactive Programming,简称RP),是一种编程范式,于1997年提出,可以简化异步编程,提供更优雅的数据绑定。一般与函数式融合在一起,所以也会叫做:函数响应式编程(Functional Reactive Programming,简称FRP)

比较著名的、成熟的响应式框架:

ReactiveCocoa
  • 简称RAC,有Objective-C、Swift版本
  • 官网: http://reactivecocoa.io/
  • github:https://github.com/ReactiveCocoa
ReactiveX
  • 简称Rx,有众多编程语言的版本,比如RxJava、RxKotlin、RxJS、RxCpp、RxPHP、RxGo、RxSwift等等
  • 官网: http://reactivex.io/
  • github: https://github.com/ReactiveX

一、 RxSwif

  • RxSwift(ReactiveX for Swift),ReactiveX的Swift版本
  • 源码:https://github.com/ReactiveX/RxSwift
  • 中文文档: https://beeth0ven.github.io/RxSwift-Chinese-Documentation/

Podfile

use_frameworks!
target 'YOUR_TARGET_NAME’ do
pod 'RxSwift', ‘6.2.0’
pod 'RxCocoa', ‘6.2.0’
end

  • RxSwift:Rx标准API的Swift实现,不包括任何iOS相关的内容
  • RxCocoa:基于RxSwift,给iOS UI控件扩展了很多Rx特性

2、RxSwif的核心角色:

  • Observable(可监听序列):产生事件,负责发送事件(Event)
  • Observer(观察者):响应事件,负责订阅Observable,监听Observable发送的事件(Event)
2.1、Observable

所有的事物都是序列
之前我们提到,Observable 可以用于描述元素异步产生的序列。这样我们生活中许多事物都可以通过它来表示,例如:

  • Observable 温度**

    你可以将温度看作是一个序列,然后监测这个温度值,最后对这个值做出响应。例如:当室温高于 33 度时,打开空调降温。

  • Observable

    你也可以把《海贼王》的动漫看作是一个序列。然后当《海贼王》更新一集时,我们就立即观看这一集。

  • Observable JSON
    你可以把网络请求的返回的 JSON 看作是一个序列。然后当取到 JSON 时,将它打印出来。

  • Observable 任务回调
    你可以把任务回调看作是一个序列。当任务结束后,提示用户任务已完成。

如何创建序列

现在我们已经可以把生活中的许多事物看作是一个序列了。那么我们要怎么创建这些序列呢?

实际上,框架已经帮我们创建好了许多常用的序列。例如:button的点击,textField的当前文本,switch的开关状态,slider的当前数值等等。

另外,有一些自定义的序列是需要我们自己创建的。这里介绍一下创建序列最基本的方法,例如,我们创建一个 [1,2,3] 的序列


import RxSwift
import RxCocoa
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let observable = Observable.create { (observe:AnyObserver) in
            observe.onNext("1")
            observe.onNext("2")
            observe.onNext("3")
            observe.onCompleted()
          return  Disposables.create()
        }

        observable.subscribe { event in
            switch event{
            case  let Event.next(data):print(data)
            case  Event.error(let error):print(error)
            case  Event.completed:print("completed")
         }
        }
    }
}

创建序列最直接的方法就是调用 Observable.create,然后在构建函数里面描述元素的产生过程。 observer.onNext(0) 就代表产生了一个元素,他的值是 0。后面又产生了 9 个元素分别是 1, 2, ... 8, 9 。最后,用 observer.onCompleted() 表示元素已经全部产生,没有更多元素了。

public enum Event {
case next(Element)
case error(Swift.Error)
case completed
}

  • next - 序列产生了一个新的元素
  • error - 创建序列时产生了一个错误,导致序列终止
  • completed - 序列的所有元素都已经成功产生,整个序列已经完成
   let  observable = Observable.just("10")
   let  observable = Observable.of("1","2","3”)
   let  observable = Observable.from(["1","2","3"])
  • 其中Observable.just("10")等价于 observe.onNext("10”) observe.onCompleted()
  • Observable.of("1","2","3”)和Observable.from(["1","2","3”])则等价于 observe.onNext("1”) observe.onNext("2")
    observe.onNext("3")
    observe.onCompleted()

我们可以用以上学习的方式来封装功能组件,例如,闭包回调:

typealias JSON = Any

let json: Observable = Observable.create { (observer) -> Disposable in

    let task = URLSession.shared.dataTask(with: ...) { data, _, error in

        guard error == nil else {
            observer.onError(error!)
            return
        }

        guard let data = data,
            let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
            else {
            observer.onError(DataError.cantParseJSON)
            return
        }

        observer.onNext(jsonObject)
        observer.onCompleted()
    }

    task.resume()

    return Disposables.create { task.cancel() }
}

json
    .subscribe(onNext: { json in
        print("取得 json 成功: \(json)")
    }, onError: { error in
        print("取得 json 失败 Error: \(error.localizedDescription)")
    }, onCompleted: {
        print("取得 json 任务成功完成")
    })
    .disposed(by: disposeBag)
2.2、Observer

在上面我们虽然只学习如何创建一个Observable,但是在上面其实我们已经接触到了Observer。回忆一下上面对Observable的监听是这样的。

  observable.subscribe { event in
            switch event{
            case  let Event.next(data):print(data)
            case  Event.error(let error):print(error)
            case  Event.completed:print("completed")
         }
    }

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

   observable.subscribe(onNext: { data in
            print(data)
     }, onError: { error in
    print("发生错误: \(error.localizedDescription)")
}, onCompleted: {
    print("任务完成")
})

那么如何自己去创建一个Observer对象呢?

import RxSwift
import RxCocoa
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let observer = AnyObserver.init { event in
            switch event {
            case .next(let data):print(data)
            case .completed:print("completed")
            case .error(let error):
                print(error)
            }
        }
        Observable.just(1).subscribe(observer)
    }
}
  • AnyObserver 可以用来描叙任意一种观察者。
Binder

import RxSwift
import RxCocoa
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
      
        let observer:Binder = Binder(self) { (target,age:Int)  in
            print(target)
        }
        Observable.just(5).bind(to: observer)
    }
}
  • Binder也是一个observer
  • Binder主要有以下两个特征:
    1、不会处理错误事件
    2、确保绑定都是在给定Scheduler上执行(默认 MainScheduler)

import RxSwift
import RxCocoa
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let lable = UILabel()
        self.view .addSubview(lable)
        lable.backgroundColor = .red
        lable.frame = CGRect(x: 100, y: 100, width: 100, height: 40)
        let binder  = Binder(lable) {(lable, str:String) in
            lable.text = str
        }
        Observable.just("test").bind(to:binder)
    }
}
  • 这里的observer是一个UI观察者,只会处理 next 事件,并且更新 UI 的操作需要在主线程上执行,因此建议使用 Binder是更好的方案。

Disposable

每当Observable被订阅时,都会返回一个Disposable实例,当调用Disposable的dispose,就相当于取消订阅。

  • dispose():立即取消订阅
  • disposed(by bag: DisposeBag):当bag销毁时,会自动调用Disposable实例的dispose。

import RxSwift
import RxCocoa
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let lable = UILabel()
        let bag = DisposeBag()
        self.view .addSubview(lable)
        lable.backgroundColor = .red
        lable.frame = CGRect(x: 100, y: 100, width: 100, height: 40)
        let binder  = Binder(lable) {(lable, str:String) in
            lable.text = str
        }
        Observable.just("test").bind(to:binder).disposed(by: bag)
    }
}

在这里bag作为控制器的成员变量,只有ViewController销毁时,bag才会被销毁,也只有这时才会被取消订阅。

  • 使用清除包(DisposeBag),我们就可以让ARC 来管理订阅的生命周期了。

2.3、补充

框架已经帮我们创建好了许多常用的序列。例如:button的点击,textField的当前文本,switch的开关状态,slider的当前数值等等。

     
        let btn = UIButton()
        let textFiled = UITextField()
        let slider = UISlider()
        let switchs = UISwitch()
    
        btn.rx.tap.subscribe { event in}.dispose()

        textFiled.rx.text.subscribe { event in}.dispose()
        
        slider.rx.value.subscribe { event in}.dispose()
        
        switchs.rx.isOn.subscribe { event in}.dispose()
      

在我们所遇到的事物中,有一部分非常特别。它们既是可监听序列也是观察者。
例如:textField的当前文本。它可以看成是由用户输入,而产生的一个文本序列。也可以是由外部文本序列,来控制当前显示内容的观察者:

// 作为可监听序列
let observable = textField.rx.text
observable.subscribe(onNext: { text in show(text: text) })

// 作为观察者
let observer = textField.rx.text
let text: Observable = ...
text.bind(to: observer)

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

扩展Binder属性

extension Reactive where Base: UIControl {
    var hidden: Binder {
        Binder(base) { button, value in
            button.isHidden = value
        }
    }

   Observable.just(1).map { "数值:\($0)" }.bind(to: button.rx.hidden).dispose()

你可能感兴趣的:(RxSwift学习一)