RxSwift文档翻译3 --Combination Operators

前言

本章节的介绍操作主要是是将多个观察序列合成一个观察序列

Combination Operators

  • startWith
    在源观察序列的元素之前发出元素,也可以理解为元队列的元素之前插入元素。并且每次不同的startWith发出或者插入的元素类似一种栈结构,后进先出的,但是在当前的startWith多个元素是不具有这种方式,还是按照队列的先进先出的
example("startWith") {
    let disposeBag = DisposeBag()

    Observable.of("🐶", "🐱", "🐭", "🐹")
        .startWith("1️⃣")
        .startWith("2️⃣")
        .startWith("3️⃣", "🅰️", "🅱️")
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
}

// 控制台打印的结果:
--- startWith example ---
3️⃣
🅰️
🅱️
2️⃣
1️⃣
🐶
🐱
🐭
🐹
  • merger
    将多个观察序列合成为一个新的观察序列,新序列发出按照源序列发出(或者说插入,添加)元素的顺序发出
example("merge") {
    let disposeBag = DisposeBag()
    
    let subject1 = PublishSubject<String>()
    let subject2 = PublishSubject<String>()
    
    Observable.of(subject1, subject2)
        .merge()
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
    
    subject1.onNext("🅰️")
    
    subject1.onNext("🅱️")
    
    subject2.onNext("①")
    
    subject2.onNext("②")
    
    subject1.onNext("🆎")
    
    subject2.onNext("③")
}

// 控制台打印的结果:
--- merge example ---
🅰️
🅱️
①
②
🆎
③
  • ** zip **
    和merger有点相似,也是将最多8个序列合成一个序列,但是zip可以将两个序列的对应顺序的元素进行合并,如果某个序列相应的顺序没有元素,则该顺序的所有序列的元素不会进行合并
    上文翻译的顺序我自认为可以理解为索引,比如队列a b c,只有a、b、c这三个序列的索引n都有元素的之后才会将三者进行合并,只要一个序列的索引n没有元素就,那么该索引n下的元素均不合并
example("zip") {
    let disposeBag = DisposeBag()
    
    let stringSubject = PublishSubject<String>()
    let intSubject = PublishSubject<Int>()
    
    Observable.zip(stringSubject, intSubject) { stringElement, intElement in
        "\(stringElement) \(intElement)"
        }
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
    
    stringSubject.onNext("🅰️")
    stringSubject.onNext("🅱️")
    
    intSubject.onNext(1)
    
    intSubject.onNext(2)
    
    stringSubject.onNext("🆎")
    intSubject.onNext(3)
}
// 控制台打印的结果:
--- zip example ---
🅰️ 1
🅱️ 2
🆎 3

// 本文不作者修改的程序1
         example("zip") {
            let disposeBag = DisposeBag()
            
            let stringSubject = PublishSubject<String>()
            let intSubject = PublishSubject<Int>()
            
            Observable.zip(stringSubject, intSubject) { stringElement, intElement in
                "\(stringElement) \(intElement)"
                }
                .subscribe(onNext: { print($0) })
                .disposed(by: disposeBag)
            
            stringSubject.onNext("🅰️")
            stringSubject.onNext("🅱️")
            
            intSubject.onNext(1)
            
            intSubject.onNext(2)
            
            stringSubject.onNext("🆎")
            intSubject.onNext(3)
            // 这里添加一个事件元素
            intSubject.onNext(4)
        }

// 控制台打印的结果:
--- zip example ---
🅰️ 1
🅱️ 2
🆎 3
  
// 本文不作者修改的程序2
example("zip") {
            let disposeBag = DisposeBag()
            
            let stringSubject = PublishSubject<String>()
            let intSubject = PublishSubject<Int>()
            let intSubject2 = PublishSubject<Int>()
            
            Observable.zip(stringSubject, intSubject, intSubject2) { stringElement, intElement, intSubject2 in
                "\(stringElement) \(intElement)"
                }
                .subscribe(onNext: { print($0) })
                .disposed(by: disposeBag)
            
            stringSubject.onNext("🅰️")
            stringSubject.onNext("🅱️")
            
            intSubject.onNext(1)
            
            intSubject.onNext(2)
            
            stringSubject.onNext("🆎")
            intSubject.onNext(3)
            
            intSubject.onNext(4)
        }  
// 控制台打印的结果:
--- zip example ---

修改程序解释:
在官方的演示程序后面我添加了两个修改的程序
1.intSubject.onNext(4),添加这一句,但是控制台没有打印,因为stringSubject没有事件元素与其配对,故没有打印
2.多添加一个观察序列intSubject2,但是由于intSubject2并没有添加任何事件元素,这意味着三个观察序列每次所以都不能成功配对,故控制台打印为空

  • combineLatest
    合并最多8个观察者序列,此操作是将每个序列最新的元素进行合并,而且在某个序列有新元素添加的时候也会执行同样的合并操作,并且新元素也会找其他序列的最新的元素进行和并购,引用官方的一张演示图,能更好的理解此操作
官方演示图
example("combineLatest") {
            let disposeBag = DisposeBag()
            
            let stringSubject = PublishSubject<String>()
            let intSubject = PublishSubject<Int>()
            
            Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
                " \(intElement)\(stringElement)"
                }
                .subscribe(onNext: { print($0) })
                .disposed(by: disposeBag)
            intSubject.onNext(1) 

            stringSubject.onNext("A")
            stringSubject.onNext("B")

            intSubject.onNext(2)
            stringSubject.onNext("C")
            stringSubject.onNext("D")
            
            intSubject.onNext(3)
            intSubject.onNext(4)
            intSubject.onNext(5)
        }

// 控制台打印的结果:
--- combineLatest example ---
 1A
 1B
 2B
 2C
 2D
 3D
 4D
 5D

combineLatest同样适用Array(或者其他的观察者序列的集合)的操作,但是要求序列集合类型必须一致,即Observer<T>的T是一种类型,否则编译前就会报错

类型不一致报错

example("Array.combineLatest") {
    let disposeBag = DisposeBag()
    
    let stringObservable = Observable.just("❤️")
    let fruitObservable = Observable.from(["🍎", "🍐", "🍊"])
    let animalObservable = Observable.of("🐶", "🐱", "🐭", "🐹")
    
    Observable.combineLatest([stringObservable, fruitObservable, animalObservable]) {
            "\($0[0]) \($0[1]) \($0[2])"
        }
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
}

// 控制台打印的结果:
--- Array.combineLatest example ---
❤️ 🍎 🐶
❤️ 🍐 🐶
❤️ 🍐 🐱
❤️ 🍊 🐱
❤️ 🍊 🐭
❤️ 🍊 🐹

  • switchLatest
    官方翻译为:将Observable序列发射的元素转换为Observable序列,并从最近的内部Observable序列中发出元素

本文作者注:官方的解释较为模糊,个人理解为switch是一个切换功能,用在序列元素也是一个观察序列的场景,假设将序列的序列定义oss,将序列定义为os,在oss的元素值设置为os1的时候,则响应os1的事件元素,当oss的元素值设置为os2的时候,此时响应os2的事件元素,此时os1即便有事件元素发出也不响应,当oss的元素值再切换到os1的时候,则再去相应os1的事件元素

/*:
 > Because the `combineLatest` variant that takes a collection passes an array of values to the selector function, it requires that all source `Observable` sequences are of the same type.
 ----
 ## `switchLatest`
 Transforms the elements emitted by an `Observable` sequence into `Observable` sequences, and emits elements from the most recent inner `Observable` sequence. [More info](http://reactivex.io/documentation/operators/switch.html)
 ![](http://upload-images.jianshu.io/upload_images/954728-c0141794880b5a6f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
 */
example("switchLatest") {
    let disposeBag = DisposeBag()
    
    let subject1 = BehaviorSubject(value: "⚽️")
    let subject2 = BehaviorSubject(value: "🍎")
    
    let variable = Variable(subject1)
        
    variable.asObservable()
        .switchLatest()
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
    
    subject1.onNext("🏈")
    subject1.onNext("🏀")
    
    variable.value = subject2
    
    subject1.onNext("⚾️")
    
    subject2.onNext("🍐")
}

// 控制台打印的结果:
--- switchLatest example ---
⚽️
🏈
🏀
🍎
🍐

此官方实例中⚾️没有打印出来,因为variable(即oss)将值切换为subject2(即os2)之后,subject1(即os1)的值⚾️对subject2没有作用,故Variable不相应⚾️,为了让大家更易于理解switchLatest,我在官方的代码最后加一句variable.value = subject1,即将variable的值切换回subject1,则subjec1的事件元素⚾️将会被相应:

example("switchLatest") {
            let disposeBag = DisposeBag()
            
            let subject1 = BehaviorSubject(value: "⚽️")
            let subject2 = BehaviorSubject(value: "🍎")
            
            let variable = Variable(subject1)
            
            variable.asObservable()
                .switchLatest()
                .subscribe(onNext: { print($0) })
                .disposed(by: disposeBag)
            
            subject1.onNext("🏈")
            subject1.onNext("🏀")
            
            variable.value = subject2
            
            subject1.onNext("⚾️")
            
            subject2.onNext("🍐")
            
            variable.value = subject1
        }
// 控制台打印的结果:
--- switchLatest example ---
⚽️
🏈
🏀
🍎
🍐
⚾️

下一篇: RxSwift文档翻译4 -- Transforming Operators

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容