iOS探索RxSwift核心

2,249 阅读4分钟

一、RxSwift核心

1、observable可观察序列

创建一个工程RxSwift01 配置对应的podfile文件:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'RxSwift01' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  pod 'RxSwift'
  pod 'RxCocoa'
  # Pods for RxSwift01

end

//在终端执行
pod install

核心问题
什么是observable可观察序列呢?

当可观察序列(Observable)发送数据项或数据项序列时观察者得到触发。这种模式促进了并发操作,因为观察者等待发送数据项的过程中无需阻塞,而是为观察者创建一个哨兵,在可观察序列发送数据项时自动触发相应的行为。

observable可观察序列又分:有限序列和无限序列

我们通过代码来分析:

//无限的
let ob = Observable<Int>.timer(.seconds(1), period: .seconds(2), scheduler: MainScheduler.instance)
ob.subscribe {num in
    print(num)
} onCompleted:{
    print("done")
}
.disposed(by: disposeBag)

//有限的
let ob1 = Observable.from([1,2,4,3])  //Observable.of(1,2,3,4) 都能达到目的
ob1.subscribe { num in
    print(num)
} onCompleted: {
    print("dnoe")
}.disposed(by: disposeBag)

运行有限序列: image.png

Observable创建:\

  1. empty:创建一个空的序列-但是只能订阅到comlete
  2. just:构建一个只有一个元素的Observable队列 - 订阅完信息自动complete
  3. of:创建一个固定数量元素的Observable序列
  4. from:从一个序列(如Array/Dictionary/Set)中创建一个Observable序列。
  5. deferred:为每个订阅者创建一个新的Observable序列
  6. generate:创建一个Observable序列,只要提供的条件值为true就可以生成值。
  7. error:创建一个不会发送任何条目并且立即终止错误的Observable序列
  8. range:创建一个Observable序列,它会发出一个系列连续的整数,然后终止
  9. timer:获取计时器Observable序列
  10. interval:底层就是封装timer

所以RxSwift也有三部曲:创建,订阅,注销。

        //1.创建序列
        let ob = Observable<Any>.create { observable in
            // 3.发送信号
            observable.onNext("班长")
            observable.onError(NSError.init(domain: "myError", code: 10080, userInfo: nil))
            return Disposables.create()
        }
        
        //2.订阅信号
        ob.subscribe { text in
            print("订阅到了:\(text)")
        } onError: { error in
            print("error:\(error)")
        } onCompleted: {
            print("完成")
        } onDisposed: {
            print("销毁")
        }

运行结果: image.png 那么为什么 observable.onNext("班长") 会响应到订阅中?

其实我们在第三步发送信号的时候,发送了3种信号,onNext,onError,Disposables 被Observable 分别接收了。

2、核心三部曲分析

  1. Observable<Any>.create其实是实现了 AnonymousObservable 匿名序列闭包->继承Producer->继承Observable->实现ObservableType 协议

  2. 订阅序列:subscribe ->创建一个AnonymousObservable订阅者->保存eventHandler->self.asObservable().subscribe(observer)->producer.subscribe->AnonymousObservableSink.run->parent.subscrbeHandler(AnyObserver(self))

  3. 发送信号:onNext->AnonymousObservable.onNext->ObserverBase.on[.next->.onCore .err\completed]->AnonymousObservable.onCore->self.eventHandler(event)

AnonymousObservableSink 核心代码:

final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType {
    typealias Element = Observer.Element 
    typealias Parent = AnonymousObservable<Element>

    // state

    private let isStopped = AtomicInt(0)
    
    //-------------省略--------------
    func on(_ event: Event<Element>) {
        #if DEBUG
            self.synchronizationTracker.register(synchronizationErrorMessage: .default)
            defer { self.synchronizationTracker.unregister() }
        #endif
        switch event {
        case .next:
            if load(self.isStopped) == 1 {
                return
            }
            self.forwardOn(event)
        case .error, .completed:
            if fetchOr(self.isStopped, 1) == 0 {
                self.forwardOn(event)
                self.dispose()
            }
        }
    }

    func run(_ parent: Parent) -> Disposable {
        parent.subscribeHandler(AnyObserver(self))
    }
}

核心流程图: image.png

3、序列继承链

先看一个小例子:

/**
         * 当用户输入用户名时,如果用户名不足 5 个字就给出红色提示语,并且无法输入密码,当用户名符合要求时才可以输入密码。
         * 同样的,当用户输入的密码不足 6 个字时也给出红色提示语。当用户名和密码有一个不符合要求时底部的登录按钮不可点击,只有当用户名和密码同时有效时按钮才可点击。
         * 当点击登录按钮后弹出一个提示框,这个提示框只是用来做演示而已。
         */
         
        let usernameValid = usernameTextFiled.rx.text.orEmpty
            .map { text in
                return text.count >= minUsernameLength
            }

//        Binder

        usernameValid.bind(to: usernameValidLabel.rx.isHidden)
            .disposed(by: disposeBag)

        usernameValid.bind(to: passwordTextFiled.rx.isEnabled)
            .disposed(by: disposeBag)
            
        let passwordValid = passwordTextFiled.rx.text.orEmpty
            .map { text in
                return text.count >= minPasswordLength
            }
        passwordValid.bind(to: passwordValidLabel.rx.isHidden)
            .disposed(by: disposeBag)

        Observable.combineLatest(usernameValid, passwordValid) { $0 && $1 }
            .bind(to: loginBtn.rx.isEnabled)
            .disposed(by: disposeBag)
        loginBtn.rx.tap.subscribe { _ in
            print("登录")
        }.disposed(by: disposeBag)

运行效果: image.png AnonymousObservable->producer(生产者)->Observable->遵循ObservableType协议 (不想贴过多的代码,能理解多少写多少)

总结

  1. 创建序列:同时创建匿名的AnonymousObservable(继承了Producer)实例_able,并保存闭包
  2. 订阅序列:Producer.subscribe创建一个_ob闭包,同时创建了AnonymousObserver(订阅者)实例_ob,并保存闭包
  3. 创建一个AnonymousObservableSink实例sink,存储了_ob
  4. sink执行run方法,调用了_able闭包, 同时创建一个AnyObserver实例anyOb-保存了sink的on方法
  5. 当_able闭包中发送信号.next .error .completed等,等于anyOb调用了on,最后回到_ob的onCore方法
  6. 执行AnonymousObserver.onCore方法,就是执行_ob闭包,根据事件类型回调我们的订阅闭包