美文网首页
RxSwift学习笔记(2) -信号的形态

RxSwift学习笔记(2) -信号的形态

作者: Dev端 | 来源:发表于2016-05-19 21:54 被阅读622次

    Subject的概念和简单创建


    Subject起的作用类似于bridge或者proxy, 它同时扮演观察者和被观察者. 又能发送信号, 又能接收信号.

    创建Subject

    let subject = PublishSubject<String>()
    
    //添加subscribe的closure
    subject.subscribe({ (event) in
        //do sth
    }).addDisposableTo(disposeBag)
    
    //发送next
    subject.onNext("🐶")
    

    Subject的种类


    ReplaySubject会在添加新的subscriber的时候给它发送之前的信号
    let subject = ReplaySubject<String>.create(bufferSize: 1)
    

    这里的bufferSize指的是发送最近的几个信号, 1就是只发送之前的一个.

    BehaviourSubject相当于上一个bufferSize = 1.
    let subject = BehaviorSubject(value: "🔴")
    

    这样的设定比较适合那种一开始需要一个初始值的模块接收信号, 有一点需要注意的是, 所有的Subject都不会自己发送complete事件.

    BehaviourSubject有一个Wrapper叫Variable, 和subject不同的是, 它在deinit的时候回自动发complete事件:

    let variable = Variable("🔴")
    variable.asObservable().addObserver("1").addDisposableTo(disposeBag)
    

    合并Subject


    StartWith

    StartWith(:)用last-in-first-out规则, 插入信号.

    Observable.of("🐶", "🐱", "🐭", "🐹")
        .startWith("1")
        .startWith("2")
        .startWith("3", "A", "B")
        .subscribeNext { print($0) }
        .addDisposableTo(disposeBag)
    

    输出: 3, A, B, 2, 1, 🐶, 🐱, 🐭, 🐹

    Merge

    merge(: )把两个Subject合并:

    Observable.of(subject1, subject2)
        .merge()
    

    subscribe上merge()出来的Observable的话, 会同时接收到两个subject发出的信号, 相当于同时observable了subject1和subject2.

    Zip

    zip(:)让同样是组合信号, 但它是一种母信号集合为基础的组合.

    Observable.zip(stringSubject, intSubject) { stringElement, intElement in
        return "\(stringElement) \(intElement)"
        }
    

    subscribe了zip出来的信号的话, 接收到的是各个信号源从subscribe的时刻开始算起相同index的值组合的结果.

    值得一提的是, 如果observable1发出了信号, observable2没发出, 那么zip出来的Observable并不会发出信号, 只有当observable2发出了, zip出来的Observable才会感应到并且往下派送信号.

    我觉得这非常适合做那种异步集合操作, 比如说我要异步下载image1, image2, image3, 我需要系统在这三张图都下载好的时候给我发送一个提示, 用zip的话, 很方便就能拿到这样一个信号了.

    CombineLatest

    Combine类似Zip, 区别在它每次向下级发送信号的时候, 母Observable的值取最近的一个.

    Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
            "\(stringElement) \(intElement)"
        }
    

    这种组合的应用场景我想到的有游戏里面的一些状态的刷新机制, Subject1之前的值都没有意义, 只要最新的值. 而Subject2一旦触发传递信号, 就会触发某个事件, 这个事件读取当前subject1和subject2的信息, 对应的就是往下一级发送信号.

    combineLatest有一个Array的拓展:

    let stringObservable = Observable.just("❤")
    let fruitObservable = ["🍎", "🍐", "🍊"].toObservable()
    let animalObservable = Observable.of("🐶", "🐱", "🐭", "🐹")
    
    [stringObservable, fruitObservable, animalObservable].combineLatest {
            "\($0[0]) \($0[1]) \($0[2])"
        }
        .subscribeNext { print($0) }
        .addDisposableTo(disposeBag)
    

    输出:

    ❤ 🍊 🐶
    ❤ 🍊 🐱
    ❤ 🍊 🐭
    ❤ 🍊 🐹
    

    监听切换

    添加这一行 switchLatest()
    当Observable的内核变化的时候, 观察者自动切换监听的对象.

    let disposeBag = DisposeBag()
    
    let subject1 = BehaviorSubject(value: "⚽️")
    let subject2 = BehaviorSubject(value: "🍎")
    
    let variable = Variable(subject1)
        
    variable.asObservable()
        .switchLatest()
        .subscribeNext { print($0) }
        .addDisposableTo(disposeBag)
    
    subject1.onNext("🏈")
    subject1.onNext("🏀")
    
    variable.value = subject2
    
    subject1.onNext("⚾️")
    
    subject2.onNext("🍐")
    

    输出:

    ⚽️
    🏈
    🏀
    🍎
    🍐
    

    通过variable做这样的操作, 我想象之中是可以做偷换信号源的功能. 比如, 对某一个API, retrieve data的方式是一样的, 我没必要重新写一遍subscriber的实现代码, 偷换一下从服务器Fetch数据的信号源就可以了.

    Referece:
    https://github.com/ReactiveX/RxSwift/tree/master/Rx.playground
    https://github.com/ReactiveX/RxSwift/tree/master/Documentation

    相关文章

      网友评论

          本文标题:RxSwift学习笔记(2) -信号的形态

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