└── README.md /README.md: -------------------------------------------------------------------------------- 1 | > 本文档内容来自于 [RxSwift](https://github.com/ReactiveX/RxSwift) 的 Playground。记录大多数 ReactiveX 的概念和操作符。 2 | 3 | (部分翻译和注解来自 [ReactiveX文档中文翻译](https://mcxiaoke.gitbooks.io/rxdocs/content/Subject.html)) 4 | 5 | # Introduction 6 | 7 | ## 为什么使用 RxSwift? 8 | 9 | 我们写的很多代码实际上是为了解决和响应外部事件。当用户操作一个控件的时候,我们需要使用 @IBAction 来响应事件。我们需要观察通知来检测键盘改变位置。当 URL Sessions 带着响应的数据返回时,我们需要提供闭包来执行我们的操作。我们还需要使用 KVO 来检测变量的值改变。这些大量的编写机制使得我们的代码结构变的更加复杂。如果有一种统一的编写机制来完成所有的这些调用/响应代码是不是更棒呢?Rx 就是为解决这些问题而生的。 10 | 11 | ## Observable 12 | 理解 RxSwift 的关键是理解 Observable 的概念。要理解它的创建,操作以及为了对变化做出响应操作而进行的订阅(subscribe)。 13 | 14 | ## 创建和订阅 Observable 15 | 要理解本框架,第一步需要理解如何创建 Observable。有很多函数可以创建 Observable。 16 | 17 | 创建 Observable 之后,如果没有订阅者订阅该 observable,那么什么事情也不会发生,所以我们将同时解释创建和订阅。 18 | 19 | ### empty 20 | 21 | `empty` 创建一个空的序列。它仅发送 `.Completed` 消息。 22 | 23 | ```swift 24 | example("empty") { 25 | let emptySequence = Observable.empty() 26 | 27 | let subscription = emptySequence 28 | .subscribe { event in 29 | print(event) 30 | } 31 | } 32 | ``` 33 | 34 | 运行结果: 35 | 36 | ``` 37 | --- empty example --- 38 | Completed 39 | ``` 40 | 41 | ### never 42 | `never` 创建一个序列,该序列永远不会发送消息,`.Completed` 消息也不会发送。 43 | 44 | ```swift 45 | example("never") { 46 | let neverSequence = Observable.never() 47 | 48 | let subscription = neverSequence 49 | .subscribe { _ in 50 | print("This block is never called.") 51 | } 52 | } 53 | ``` 54 | 55 | 运行结果: 56 | ``` 57 | --- never example --- 58 | ``` 59 | 60 | 61 | ### just 62 | `just` 代表只包含一个元素的序列。它将向订阅者发送两个消息,第一个消息是其中元素的值,另一个是 `.Completed`。 63 | 64 | ```swift 65 | example("just") { 66 | let singleElementSequence = Observable.just(32) 67 | 68 | let subscription = singleElementSequence 69 | .subscribe { event in 70 | print(event) 71 | } 72 | } 73 | ``` 74 | 75 | 运行结果: 76 | 77 | ``` 78 | --- just example --- 79 | Next(32) 80 | Completed 81 | ``` 82 | 83 | ### sequenceOf 84 | `sequenceOf` 通过固定数目的元素创建一个序列 85 | 86 | ```swift 87 | example("sequenceOf") { 88 | let sequenceOfElements/* : Observable */ = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 89 | 90 | let subscription = sequenceOfElements 91 | .subscribe { event in 92 | print(event) 93 | } 94 | } 95 | ``` 96 | 97 | 运行结果: 98 | 99 | ``` 100 | --- sequenceOf example --- 101 | Next(0) 102 | Next(1) 103 | Next(2) 104 | Next(3) 105 | Next(4) 106 | Next(5) 107 | Next(6) 108 | Next(7) 109 | Next(8) 110 | Next(9) 111 | Completed 112 | ``` 113 | 114 | ### toObservable 115 | `toObservable` 在一个数组的基础上创建一个序列 116 | 117 | ```swift 118 | example("toObservable") { 119 | let sequenceFromArray = [1, 2, 3, 4, 5].toObservable() 120 | 121 | let subscription = sequenceFromArray 122 | .subscribe { event in 123 | print(event) 124 | } 125 | } 126 | ``` 127 | 128 | 运行结果: 129 | 130 | ``` 131 | --- toObservable example --- 132 | Next(1) 133 | Next(2) 134 | Next(3) 135 | Next(4) 136 | Next(5) 137 | Completed 138 | ``` 139 | 140 | 141 | ### create 142 | `create` 使用 Swift 闭包来创建一个序列。该例子中,创建了 `just` 操作符的自定义版本。 143 | 144 | ```swift 145 | example("create") { 146 | let myJust = { (singleElement: Int) -> Observable in 147 | return Observable.create { observer in 148 | observer.on(.Next(singleElement)) 149 | observer.on(.Completed) 150 | 151 | return NopDisposable.instance 152 | } 153 | } 154 | 155 | let subscription = myJust(5) 156 | .subscribe { event in 157 | print(event) 158 | } 159 | } 160 | ``` 161 | 162 | 运行结果: 163 | 164 | ``` 165 | --- create example --- 166 | Next(5) 167 | Completed 168 | ``` 169 | 170 | ### generate 171 | `generate` 创建的序列可以自己生成它的值,并且在之前值的基础上来判断什么时候结束。 172 | 173 | ```swift 174 | example("generate") { 175 | let generated = Observable.generate( 176 | initialState: 0, 177 | condition: { $0 < 3 }, 178 | iterate: { $0 + 1 } 179 | ) 180 | 181 | let subscription = generated 182 | .subscribe { event in 183 | print(event) 184 | } 185 | } 186 | ``` 187 | 188 | 运行结果: 189 | 190 | ``` 191 | --- generate example --- 192 | Next(0) 193 | Next(1) 194 | Next(2) 195 | Completed 196 | ``` 197 | 198 | 199 | ### error 200 | 创建一个不发送任何 item 的 Observable,以 error 中指 201 | 202 | ```swift 203 | example("error") { 204 | let error = NSError(domain: "Test", code: -1, userInfo: nil) 205 | 206 | let erroredSequence = Observable.error(error) 207 | 208 | let subscription = erroredSequence 209 | .subscribe { event in 210 | print(event) 211 | } 212 | } 213 | ``` 214 | 215 | 运行结果: 216 | 217 | ``` 218 | --- error example --- 219 | Error(Error Domain=Test Code=-1 "(null)") 220 | ``` 221 | 222 | 223 | ### deferred 224 | 225 | 直到 observer 订阅之后才创建 Observable,并且为每一个 observer 创建一个全新的 Observable 226 | do not create the Observable until the observer subscribes, and create a fresh Observable for each observer 227 | 228 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/defer.png) 229 | 230 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/defer.html ) 231 | 232 | ```swift 233 | example("deferred") { 234 | let deferredSequence: Observable = Observable.deferred { 235 | print("creating") 236 | return Observable.create { observer in 237 | print("emmiting") 238 | observer.on(.Next(0)) 239 | observer.on(.Next(1)) 240 | observer.on(.Next(2)) 241 | 242 | return NopDisposable.instance 243 | } 244 | } 245 | 246 | _ = deferredSequence 247 | .subscribe { event in 248 | print(event) 249 | } 250 | 251 | _ = deferredSequence 252 | .subscribe { event in 253 | print(event) 254 | } 255 | } 256 | ``` 257 | 258 | 运行结果: 259 | 260 | ``` 261 | --- deferred example --- 262 | creating 263 | emmiting 264 | Next(0) 265 | Next(1) 266 | Next(2) 267 | creating 268 | emmiting 269 | Next(0) 270 | Next(1) 271 | Next(2) 272 | ``` 273 | 274 | 在 RxCocoa 库中还有很多其他非常有用的方法,例如: 275 | 276 | * `rx_observe` 存在于所有 NSObject 子类中,封装了 KVO 277 | * `rx_tap` 存在于 button 中,封装了 @IBActions 278 | * `rx_notification` 封装了 NotificationCenter 279 | * ... 280 | 281 | 282 | # Subjects 283 | Subject 可以看成是一个桥梁或者代理,在某些ReactiveX实现中,它同时充当了 Observer 和 Observable 的角色。因为它是一个Observer,它可以订阅一个或多个 Observable;又因为它是一个 Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。 284 | 285 | 辅助函数: 286 | 287 | ```swift 288 | func writeSequenceToConsole(name: String, sequence: O) -> Disposable { 289 | return sequence 290 | .subscribe { e in 291 | print("Subscription: \(name), event: \(e)") 292 | } 293 | } 294 | ``` 295 | 296 | ## PublishSubject 297 | 298 | `PublishSubject` 只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。 299 | 300 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishsubject.png) 301 | 302 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/publishsubject_error.png) 303 | 304 | ```swift 305 | example("PublishSubject") { 306 | let disposeBag = DisposeBag() 307 | 308 | let subject = PublishSubject() 309 | writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag) 310 | subject.on(.Next("a")) 311 | subject.on(.Next("b")) 312 | writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag) 313 | subject.on(.Next("c")) 314 | subject.on(.Next("d")) 315 | } 316 | ``` 317 | 318 | 运行结果: 319 | 320 | ``` 321 | --- PublishSubject example --- 322 | Subscription: 1, event: Next(a) 323 | Subscription: 1, event: Next(b) 324 | Subscription: 1, event: Next(c) 325 | Subscription: 2, event: Next(c) 326 | Subscription: 1, event: Next(d) 327 | Subscription: 2, event: Next(d) 328 | ``` 329 | 330 | ## ReplaySubject 331 | 332 | `ReplaySubject` 会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。当一个新的 observer 订阅了一个 `ReplaySubject` 之后,他将会收到当前缓存在 buffer 中的数据和这之后产生的新数据。在下面的例子中,缓存大小为 `1` 所以 observer 将最多能够收到订阅时间点之前的一个数据。例如,`Subscription: 2` 能够收到消息 `"b"`,而这个消息是在他订阅之前发送的,但是没有办法收到消息 `"a"` 因为缓存的容量小于 `2`。 333 | 334 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/replaysubject.png) 335 | 336 | ```swift 337 | example("ReplaySubject") { 338 | let disposeBag = DisposeBag() 339 | let subject = ReplaySubject.create(bufferSize: 1) 340 | 341 | writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag) 342 | subject.on(.Next("a")) 343 | subject.on(.Next("b")) 344 | writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag) 345 | subject.on(.Next("c")) 346 | subject.on(.Next("d")) 347 | } 348 | ``` 349 | 350 | 运行结果: 351 | 352 | ``` 353 | --- ReplaySubject example --- 354 | Subscription: 1, event: Next(a) 355 | Subscription: 1, event: Next(b) 356 | Subscription: 2, event: Next(b) 357 | Subscription: 1, event: Next(c) 358 | Subscription: 2, event: Next(c) 359 | Subscription: 1, event: Next(d) 360 | Subscription: 2, event: Next(d) 361 | ``` 362 | 363 | ## BehaviorSubject 364 | 365 | 当观察者订阅 `BehaviorSubject` 时,它开始发射原始 Observable 最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。 366 | 367 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/behaviorsubject.png) 368 | 369 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/behaviorsubject_error.png) 370 | 371 | ```swift 372 | example("BehaviorSubject") { 373 | let disposeBag = DisposeBag() 374 | 375 | let subject = BehaviorSubject(value: "z") 376 | writeSequenceToConsole("1", sequence: subject).addDisposableTo(disposeBag) 377 | subject.on(.Next("a")) 378 | subject.on(.Next("b")) 379 | writeSequenceToConsole("2", sequence: subject).addDisposableTo(disposeBag) 380 | subject.on(.Next("c")) 381 | subject.on(.Next("d")) 382 | subject.on(.Completed) 383 | } 384 | ``` 385 | 386 | 运行结果: 387 | 388 | ``` 389 | --- BehaviorSubject example --- 390 | Subscription: 1, event: Next(z) 391 | Subscription: 1, event: Next(a) 392 | Subscription: 1, event: Next(b) 393 | Subscription: 2, event: Next(b) 394 | Subscription: 1, event: Next(c) 395 | Subscription: 2, event: Next(c) 396 | Subscription: 1, event: Next(d) 397 | Subscription: 2, event: Next(d) 398 | Subscription: 1, event: Completed 399 | Subscription: 2, event: Completed 400 | ``` 401 | 402 | ## Variable 403 | 404 | `Variable` 封装了 `BehaviorSubject`。使用 variable 的好处是 variable 将不会显式的发送 `Error` 或者 `Completed`。在 deallocated 的时候,`Variable` 会自动的发送 complete 事件。 405 | 406 | ```swift 407 | example("Variable") { 408 | let disposeBag = DisposeBag() 409 | let variable = Variable("z") 410 | writeSequenceToConsole("1", sequence: variable.asObservable()).addDisposableTo(disposeBag) 411 | variable.value = "a" 412 | variable.value = "b" 413 | writeSequenceToConsole("2", sequence: variable.asObservable()).addDisposableTo(disposeBag) 414 | variable.value = "c" 415 | variable.value = "d" 416 | } 417 | ``` 418 | 419 | 运行结果: 420 | 421 | ``` 422 | --- Variable example --- 423 | Subscription: 1, event: Next(z) 424 | Subscription: 1, event: Next(a) 425 | Subscription: 1, event: Next(b) 426 | Subscription: 2, event: Next(b) 427 | Subscription: 1, event: Next(c) 428 | Subscription: 2, event: Next(c) 429 | Subscription: 1, event: Next(d) 430 | Subscription: 2, event: Next(d) 431 | Subscription: 1, event: Completed 432 | Subscription: 2, event: Completed 433 | ``` 434 | 435 | 436 | ## 变换操作 437 | 438 | 下面列出了可用于对 Observable 发射的数据执行变换操作的各种操作符。 439 | 440 | ### `map` / `select` 441 | 442 | 对序列的每一项都应用一个函数来变换 Observable 发射的数据序列 443 | 444 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/map.png) 445 | 446 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/map.html ) 447 | 448 | ```swift 449 | example("map") { 450 | let originalSequence = Observable.of(1, 2, 3) 451 | 452 | _ = originalSequence 453 | .map { number in 454 | number * 2 455 | } 456 | .subscribe { print($0) } 457 | } 458 | ``` 459 | 460 | 运行结果: 461 | 462 | ``` 463 | --- map example --- 464 | Next(2) 465 | Next(4) 466 | Next(6) 467 | Completed 468 | ``` 469 | 470 | 471 | 472 | ### `flatMap` 473 | 474 | 将每个 Obserable 发射的数据变换为 Observable 的集合,然后将其 "拍扁"(降维 flatten)成一个 Observable。 475 | 476 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/flatmap.png) 477 | 478 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/flatmap.html ) 479 | 480 | ```swift 481 | example("flatMap") { 482 | let sequenceInt = Observable.of(1, 2, 3) 483 | 484 | let sequenceString = Observable.of("A", "B", "C", "D", "E", "F", "--") 485 | 486 | _ = sequenceInt 487 | .flatMap { (x:Int) -> Observable in 488 | print("from sequenceInt \(x)") 489 | return sequenceString 490 | } 491 | .subscribe { 492 | print($0) 493 | } 494 | } 495 | ``` 496 | 497 | 运行结果: 498 | 499 | ``` 500 | --- flatMap example --- 501 | from sequenceInt 1 502 | Next(A) 503 | Next(B) 504 | Next(C) 505 | Next(D) 506 | Next(E) 507 | Next(F) 508 | Next(--) 509 | from sequenceInt 2 510 | Next(A) 511 | Next(B) 512 | Next(C) 513 | Next(D) 514 | Next(E) 515 | Next(F) 516 | Next(--) 517 | from sequenceInt 3 518 | Next(A) 519 | Next(B) 520 | Next(C) 521 | Next(D) 522 | Next(E) 523 | Next(F) 524 | Next(--) 525 | Completed 526 | ``` 527 | 528 | ### `scan` 529 | 530 | 对 Observable 发射的每一项数据应用一个函数,然后按顺序依次发射每一个值 531 | 532 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/scan.png) 533 | 534 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/scan.html ) 535 | 536 | ```swift 537 | example("scan") { 538 | let sequenceToSum = Observable.of(0, 1, 2, 3, 4, 5) 539 | 540 | _ = sequenceToSum 541 | .scan(0) { acum, elem in 542 | acum + elem 543 | } 544 | .subscribe { 545 | print($0) 546 | } 547 | } 548 | ``` 549 | 550 | 运行结果: 551 | 552 | ``` 553 | --- scan example --- 554 | Next(0) 555 | Next(1) 556 | Next(3) 557 | Next(6) 558 | Next(10) 559 | Next(15) 560 | Completed 561 | ``` 562 | 563 | ## 过滤操作 564 | 565 | 从源 Observable 中选择特定的数据发送 566 | 567 | ### `filter` 568 | 569 | 只发送 Observable 中通过特定测试的数据 570 | 571 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/filter.png) 572 | 573 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/filter.html ) 574 | 575 | ```swift 576 | example("filter") { 577 | let subscription = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 578 | .filter { 579 | $0 % 2 == 0 580 | } 581 | .subscribe { 582 | print($0) 583 | } 584 | } 585 | ``` 586 | 587 | 运行结果: 588 | 589 | ``` 590 | --- filter example --- 591 | Next(0) 592 | Next(2) 593 | Next(4) 594 | Next(6) 595 | Next(8) 596 | Completed 597 | ``` 598 | 599 | 600 | ### `distinctUntilChanged` 601 | 602 | 过滤掉连续重复的数据 603 | 604 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/distinct.png) 605 | 606 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/distinct.html ) 607 | 608 | ```swift 609 | example("distinctUntilChanged") { 610 | let subscription = Observable.of(1, 2, 3, 1, 1, 4) 611 | .distinctUntilChanged() 612 | .subscribe { 613 | print($0) 614 | } 615 | } 616 | ``` 617 | 618 | 运行结果: 619 | 620 | ``` 621 | --- distinctUntilChanged example --- 622 | Next(1) 623 | Next(2) 624 | Next(3) 625 | Next(1) 626 | Next(4) 627 | Completed 628 | ``` 629 | 630 | 631 | ### `take` 632 | 633 | 仅发送 Observable 的前 n 个数据项 634 | 635 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/take.png) 636 | 637 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/take.html ) 638 | 639 | ```swfit 640 | example("take") { 641 | let subscription = Observable.of(1, 2, 3, 4, 5, 6) 642 | .take(3) 643 | .subscribe { 644 | print($0) 645 | } 646 | } 647 | ``` 648 | 649 | 运行结果: 650 | 651 | ``` 652 | --- take example --- 653 | Next(1) 654 | Next(2) 655 | Next(3) 656 | Completed 657 | ``` 658 | 659 | ## 结合操作(Combination operators) 660 | 661 | 将多个 Observable 结合成一个 Observable 662 | 663 | 664 | ### `startWith` 665 | 666 | 在数据序列的开头增加一些数据 667 | 668 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/startwith.png) 669 | 670 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/startwith.html ) 671 | 672 | ```swift 673 | example("startWith") { 674 | 675 | let subscription = Observable.of(4, 5, 6, 7, 8, 9) 676 | .startWith(3) 677 | .startWith(2) 678 | .startWith(1) 679 | .startWith(0) 680 | .subscribe { 681 | print($0) 682 | } 683 | } 684 | ``` 685 | 686 | 运行结果: 687 | 688 | ``` 689 | --- startWith example --- 690 | Next(0) 691 | Next(1) 692 | Next(2) 693 | Next(3) 694 | Next(4) 695 | Next(5) 696 | Next(6) 697 | Next(7) 698 | Next(8) 699 | Next(9) 700 | Completed 701 | ``` 702 | 703 | 704 | ### `combineLatest` 705 | 706 | 当两个 Observables 中的任何一个发射了一个数据时,通过一个指定的函数组合每个Observable发射的最新数据(一共两个数据),然后发射这个函数的结果 707 | 708 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/combinelatest.png) 709 | 710 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/combinelatest.html ) 711 | 712 | ```swift 713 | example("combineLatest 1") { 714 | let intOb1 = PublishSubject() 715 | let intOb2 = PublishSubject() 716 | 717 | _ = Observable.combineLatest(intOb1, intOb2) { 718 | "\($0) \($1)" 719 | } 720 | .subscribe { 721 | print($0) 722 | } 723 | 724 | intOb1.on(.Next("A")) 725 | 726 | intOb2.on(.Next(1)) 727 | 728 | intOb1.on(.Next("B")) 729 | 730 | intOb2.on(.Next(2)) 731 | } 732 | ``` 733 | 734 | 运行结果: 735 | 736 | ``` 737 | --- combineLatest 1 example --- 738 | Next(A 1) 739 | Next(B 1) 740 | Next(B 2) 741 | ``` 742 | 743 | 为了能够产生结果,两个序列中都必须保证至少有一个元素 744 | 745 | ```swift 746 | example("combineLatest 2") { 747 | let intOb1 = Observable.just(2) 748 | let intOb2 = Observable.of(0, 1, 2, 3, 4) 749 | 750 | _ = Observable.combineLatest(intOb1, intOb2) { 751 | $0 * $1 752 | } 753 | .subscribe { 754 | print($0) 755 | } 756 | } 757 | ``` 758 | 759 | 运行结果: 760 | 761 | ``` 762 | --- combineLatest 2 example --- 763 | Next(0) 764 | Next(2) 765 | Next(4) 766 | Next(6) 767 | Next(8) 768 | Completed 769 | ``` 770 | 771 | Combine latest 有超过 2 个参数的版本 772 | 773 | ```swift 774 | example("combineLatest 3") { 775 | let intOb1 = Observable.just(2) 776 | let intOb2 = Observable.of(0, 1, 2, 3) 777 | let intOb3 = Observable.of(0, 1, 2, 3, 4) 778 | 779 | _ = Observable.combineLatest(intOb1, intOb2, intOb3) { 780 | ($0 + $1) * $2 781 | } 782 | .subscribe { 783 | print($0) 784 | } 785 | } 786 | ``` 787 | 788 | 运行结果: 789 | 790 | ``` 791 | --- combineLatest 3 example --- 792 | Next(0) 793 | Next(5) 794 | Next(10) 795 | Next(15) 796 | Next(20) 797 | Completed 798 | ``` 799 | 800 | Combinelatest 可以作用于不同数据类型的序列 801 | 802 | ```swift 803 | example("combineLatest 4") { 804 | let intOb = Observable.just(2) 805 | let stringOb = Observable.just("a") 806 | 807 | _ = Observable.combineLatest(intOb, stringOb) { 808 | "\($0) " + $1 809 | } 810 | .subscribe { 811 | print($0) 812 | } 813 | } 814 | ``` 815 | 816 | 运行结果: 817 | 818 | ``` 819 | --- combineLatest 4 example --- 820 | Next(2 a) 821 | Completed 822 | ``` 823 | 824 | `combineLatest` 方法可以在 Array 上使用,数组元素类型必须遵循 `ObservableType` 协议 825 | 数组中的元素类型必须为 `Observables` 826 | 827 | ```swift 828 | example("combineLatest 5") { 829 | let intOb1 = Observable.just(2) 830 | let intOb2 = Observable.of(0, 1, 2, 3) 831 | let intOb3 = Observable.of(0, 1, 2, 3, 4) 832 | 833 | _ = [intOb1, intOb2, intOb3].combineLatest { intArray -> Int in 834 | Int((intArray[0] + intArray[1]) * intArray[2]) 835 | } 836 | .subscribe { (event: Event) -> Void in 837 | print(event) 838 | } 839 | } 840 | ``` 841 | 842 | ### `withLatestFrom` 843 | 844 | Merges two observable sequences into one observable sequence by using latest element from the second sequence every time when self emitts an element. 845 | 846 | 将两个 Observable 序列合并为一个。每当 self 队列发射一个元素时,从第二个序列中取出最新的一个值。 847 | 848 | ```swift 849 | example("withLatestFrom") { 850 | let subjectA = PublishSubject() 851 | let subjectB = PublishSubject() 852 | 853 | subjectA 854 | .withLatestFrom(subjectB) 855 | .subscribeNext({ (data) in 856 | print(data) 857 | }) 858 | 859 | subjectA.onNext("a1") 860 | subjectB.onNext("b1") 861 | subjectA.onNext("a2") 862 | subjectA.onNext("a3") 863 | subjectB.onNext("b2") 864 | subjectA.onNext("a4") 865 | } 866 | ``` 867 | 868 | 运行结果: 869 | 870 | ``` 871 | --- withLatestFrom example --- 872 | b1 873 | b1 874 | b2 875 | ``` 876 | 877 | ### `zip` 878 | 879 | 使用一个函数组合多个Observable发射的数据集合,然后再发射这个结果(从序列中依次取数据) 880 | 881 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/zip.png) 882 | 883 | [更多相关内容请查看 reactive.io](http://reactivex.io/documentation/operators/zip.html) 884 | 885 | ```swift 886 | example("zip 1") { 887 | let intOb1 = PublishSubject() 888 | let intOb2 = PublishSubject() 889 | 890 | _ = Observable.zip(intOb1, intOb2) { 891 | "\($0) \($1)" 892 | } 893 | .subscribe { 894 | print($0) 895 | } 896 | 897 | intOb1.on(.Next("A")) 898 | 899 | intOb2.on(.Next(1)) 900 | 901 | intOb1.on(.Next("B")) 902 | 903 | intOb1.on(.Next("C")) 904 | 905 | intOb2.on(.Next(2)) 906 | } 907 | ``` 908 | 909 | 运行结果: 910 | 911 | ``` 912 | --- zip 1 example --- 913 | Next(A 1) 914 | Next(B 2) 915 | ``` 916 | 917 | ```swift 918 | example("zip 2") { 919 | let intOb1 = Observable.just(2) 920 | 921 | let intOb2 = Observable.of(0, 1, 2, 3, 4) 922 | 923 | _ = Observable.zip(intOb1, intOb2) { 924 | $0 * $1 925 | } 926 | .subscribe { 927 | print($0) 928 | } 929 | } 930 | ``` 931 | 932 | 运行结果: 933 | 934 | ``` 935 | --- zip 2 example --- 936 | Next(0) 937 | Completed 938 | ``` 939 | 940 | 941 | ```swift 942 | example("zip 3") { 943 | let intOb1 = Observable.of(0, 1) 944 | let intOb2 = Observable.of(0, 1, 2, 3) 945 | let intOb3 = Observable.of(0, 1, 2, 3, 4) 946 | 947 | _ = Observable.zip(intOb1, intOb2, intOb3) { 948 | ($0 + $1) * $2 949 | } 950 | .subscribe { 951 | print($0) 952 | } 953 | } 954 | ``` 955 | 956 | 运行结果: 957 | 958 | ``` 959 | --- zip 3 example --- 960 | Next(0) 961 | Next(2) 962 | Completed 963 | ``` 964 | 965 | 966 | ### `merge` 967 | 968 | 合并多个 Observables 的组合成一个 969 | 970 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/merge.png) 971 | 972 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/merge.html ) 973 | 974 | ```swift 975 | example("merge 1") { 976 | let subject1 = PublishSubject() 977 | let subject2 = PublishSubject() 978 | 979 | _ = Observable.of(subject1, subject2) 980 | .merge() 981 | .subscribeNext { int in 982 | print(int) 983 | } 984 | 985 | subject1.on(.Next(20)) 986 | subject1.on(.Next(40)) 987 | subject1.on(.Next(60)) 988 | subject2.on(.Next(1)) 989 | subject1.on(.Next(80)) 990 | subject1.on(.Next(100)) 991 | subject2.on(.Next(1)) 992 | } 993 | ``` 994 | 995 | 运行结果: 996 | 997 | ``` 998 | --- merge 1 example --- 999 | 20 1000 | 40 1001 | 60 1002 | 1 1003 | 80 1004 | 100 1005 | 1 1006 | ``` 1007 | 1008 | ```swift 1009 | example("merge 2") { 1010 | let subject1 = PublishSubject() 1011 | let subject2 = PublishSubject() 1012 | 1013 | _ = Observable.of(subject1, subject2) 1014 | .merge(maxConcurrent: 2) 1015 | .subscribe { 1016 | print($0) 1017 | } 1018 | 1019 | subject1.on(.Next(20)) 1020 | subject1.on(.Next(40)) 1021 | subject1.on(.Next(60)) 1022 | subject2.on(.Next(1)) 1023 | subject1.on(.Next(80)) 1024 | subject1.on(.Next(100)) 1025 | subject2.on(.Next(1)) 1026 | } 1027 | ``` 1028 | 1029 | 运行结果: 1030 | 1031 | ``` 1032 | --- merge 2 example --- 1033 | Next(20) 1034 | Next(40) 1035 | Next(60) 1036 | Next(1) 1037 | Next(80) 1038 | Next(100) 1039 | Next(1) 1040 | ``` 1041 | 1042 | 1043 | ### `switchLatest` 1044 | 1045 | 将一个发射多个 Observables 的 Observable 转换成另一个单独的 Observable,后者发射那些 Observables 最近发射的数据项 1046 | 1047 | Switch 订阅一个发射多个 Observables 的 Observable。它每次观察那些 Observables 中的一个,Switch 返回的这个Observable取消订阅前一个发射数据的 Observable,开始发射最近的Observable 发射的数据。注意:当原始 Observable 发射了一个新的 Observable 时(不是这个新的 Observable 发射了一条数据时),它将取消订阅之前的那个 Observable。这意味着,在后来那个 Observable 产生之后到它开始发射数据之前的这段时间里,前一个 Observable 发射的数据将被丢弃 1048 | 1049 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/switch.png) 1050 | 1051 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/switch.html ) 1052 | 1053 | 1054 | ```swift 1055 | example("switchLatest") { 1056 | let var1 = Variable(0) 1057 | 1058 | let var2 = Variable(200) 1059 | 1060 | // var3 is like an Observable> 1061 | let var3 = Variable(var1.asObservable()) 1062 | 1063 | let d = var3 1064 | .asObservable() 1065 | .switchLatest() 1066 | .subscribe { 1067 | print($0) 1068 | } 1069 | 1070 | var1.value = 1 1071 | var1.value = 2 1072 | var1.value = 3 1073 | var1.value = 4 1074 | 1075 | var3.value = var2.asObservable() 1076 | 1077 | var2.value = 201 1078 | 1079 | var1.value = 5 1080 | var1.value = 6 1081 | var1.value = 7 1082 | } 1083 | ``` 1084 | 1085 | 运行结果: 1086 | 1087 | ``` 1088 | --- switchLatest example --- 1089 | Next(0) 1090 | Next(1) 1091 | Next(2) 1092 | Next(3) 1093 | Next(4) 1094 | Next(200) 1095 | Next(201) 1096 | Completed 1097 | ``` 1098 | 1099 | 1100 | ## Error Handling Operators 1101 | 1102 | 下面的操作符帮助我们从 Observable 发射的 error 通知做出响应或者从错误中恢复。 1103 | 1104 | ### `catchError` 1105 | 1106 | 收到 `Error` 通知之后,转而发送一个没有错误的序列。 1107 | 1108 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/catch.png) 1109 | 1110 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/catch.html ) 1111 | 1112 | 1113 | ```swift 1114 | example("catchError 1") { 1115 | let sequenceThatFails = PublishSubject() 1116 | let recoverySequence = Observable.of(100, 200, 300, 400) 1117 | 1118 | _ = sequenceThatFails 1119 | .catchError { error in 1120 | return recoverySequence 1121 | } 1122 | .subscribe { 1123 | print($0) 1124 | } 1125 | 1126 | sequenceThatFails.on(.Next(1)) 1127 | sequenceThatFails.on(.Next(2)) 1128 | sequenceThatFails.on(.Next(3)) 1129 | sequenceThatFails.on(.Next(4)) 1130 | sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil))) 1131 | } 1132 | ``` 1133 | 1134 | 运行结果: 1135 | 1136 | ``` 1137 | --- catchError 1 example --- 1138 | Next(1) 1139 | Next(2) 1140 | Next(3) 1141 | Next(4) 1142 | Next(100) 1143 | Next(200) 1144 | Next(300) 1145 | Next(400) 1146 | Completed 1147 | ``` 1148 | 1149 | ```swift 1150 | example("catchError 2") { 1151 | let sequenceThatFails = PublishSubject() 1152 | 1153 | _ = sequenceThatFails 1154 | .catchErrorJustReturn(100) 1155 | .subscribe { 1156 | print($0) 1157 | } 1158 | 1159 | sequenceThatFails.on(.Next(1)) 1160 | sequenceThatFails.on(.Next(2)) 1161 | sequenceThatFails.on(.Next(3)) 1162 | sequenceThatFails.on(.Next(4)) 1163 | sequenceThatFails.on(.Error(NSError(domain: "Test", code: 0, userInfo: nil))) 1164 | } 1165 | ``` 1166 | 1167 | 运行结果: 1168 | 1169 | ``` 1170 | --- catchError 2 example --- 1171 | Next(1) 1172 | Next(2) 1173 | Next(3) 1174 | Next(4) 1175 | Next(100) 1176 | Completed 1177 | ``` 1178 | 1179 | ### `retry` 1180 | 1181 | 如果原始 Observable 遇到错误,重新订阅,心里默念,不会出错不会出错... 1182 | 1183 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/retry.png) 1184 | 1185 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/retry.html ) 1186 | 1187 | 1188 | ```swift 1189 | example("retry") { 1190 | var count = 1 // bad practice, only for example purposes 1191 | let funnyLookingSequence = Observable.create { observer in 1192 | let error = NSError(domain: "Test", code: 0, userInfo: nil) 1193 | observer.on(.Next(0)) 1194 | observer.on(.Next(1)) 1195 | observer.on(.Next(2)) 1196 | if count < 2 { 1197 | observer.on(.Error(error)) 1198 | count += 1 1199 | } 1200 | observer.on(.Next(3)) 1201 | observer.on(.Next(4)) 1202 | observer.on(.Next(5)) 1203 | observer.on(.Completed) 1204 | 1205 | return NopDisposable.instance 1206 | } 1207 | 1208 | _ = funnyLookingSequence 1209 | .retry() 1210 | .subscribe { 1211 | print($0) 1212 | } 1213 | } 1214 | ``` 1215 | 1216 | 运行结果: 1217 | 1218 | ``` 1219 | --- retry example --- 1220 | Next(0) 1221 | Next(1) 1222 | Next(2) 1223 | Next(0) 1224 | Next(1) 1225 | Next(2) 1226 | Next(3) 1227 | Next(4) 1228 | Next(5) 1229 | Completed 1230 | ``` 1231 | 1232 | ## Observable Utility Operators 1233 | 1234 | 下面的操作符可以当做一个工具集,方便操作 Observable 1235 | 1236 | ### `subscribe` 1237 | 1238 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/subscribe.html ) 1239 | 1240 | ```swift 1241 | example("subscribe") { 1242 | let sequenceOfInts = PublishSubject() 1243 | 1244 | _ = sequenceOfInts 1245 | .subscribe { 1246 | print($0) 1247 | } 1248 | 1249 | sequenceOfInts.on(.Next(1)) 1250 | sequenceOfInts.on(.Completed) 1251 | } 1252 | ``` 1253 | 1254 | 运行结果: 1255 | 1256 | ``` 1257 | --- subscribe example --- 1258 | Next(1) 1259 | Completed 1260 | ``` 1261 | 1262 | 下面是几个 `subscribe` 操作符的变体 1263 | 1264 | 1265 | ### `subscribeNext` 1266 | 1267 | ```swift 1268 | example("subscribeNext") { 1269 | let sequenceOfInts = PublishSubject() 1270 | 1271 | _ = sequenceOfInts 1272 | .subscribeNext { 1273 | print($0) 1274 | } 1275 | 1276 | sequenceOfInts.on(.Next(1)) 1277 | sequenceOfInts.on(.Completed) 1278 | } 1279 | ``` 1280 | 1281 | 运行结果: 1282 | 1283 | ``` 1284 | --- subscribeNext example --- 1285 | 1 1286 | ``` 1287 | 1288 | 1289 | ### `subscribeCompleted` 1290 | 1291 | ```swift 1292 | example("subscribeCompleted") { 1293 | let sequenceOfInts = PublishSubject() 1294 | 1295 | _ = sequenceOfInts 1296 | .subscribeCompleted { 1297 | print("It's completed") 1298 | } 1299 | 1300 | sequenceOfInts.on(.Next(1)) 1301 | sequenceOfInts.on(.Completed) 1302 | } 1303 | ``` 1304 | 1305 | 运行结果: 1306 | 1307 | ``` 1308 | --- subscribeCompleted example --- 1309 | It's completed 1310 | ``` 1311 | 1312 | 1313 | ### `subscribeError` 1314 | 1315 | ```swift 1316 | example("subscribeError") { 1317 | let sequenceOfInts = PublishSubject() 1318 | 1319 | _ = sequenceOfInts 1320 | .subscribeError { error in 1321 | print(error) 1322 | } 1323 | 1324 | sequenceOfInts.on(.Next(1)) 1325 | sequenceOfInts.on(.Error(NSError(domain: "Examples", code: -1, userInfo: nil))) 1326 | } 1327 | ``` 1328 | 1329 | 运行结果: 1330 | 1331 | ``` 1332 | --- subscribeError example --- 1333 | Error Domain=Examples Code=-1 "(null)" 1334 | ``` 1335 | 1336 | ### `doOn` 1337 | 1338 | 注册一个操作来监听事件的生命周期 1339 | (register an action to take upon a variety of Observable lifecycle events) 1340 | 1341 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/do.png) 1342 | 1343 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/do.html ) 1344 | 1345 | 1346 | ```swift 1347 | example("doOn") { 1348 | let sequenceOfInts = PublishSubject() 1349 | 1350 | _ = sequenceOfInts 1351 | .doOn { 1352 | print("Intercepted event \($0)") 1353 | } 1354 | .subscribe { 1355 | print($0) 1356 | } 1357 | 1358 | sequenceOfInts.on(.Next(1)) 1359 | sequenceOfInts.on(.Completed) 1360 | } 1361 | ``` 1362 | 1363 | 运行结果: 1364 | 1365 | ``` 1366 | --- doOn example --- 1367 | Intercepted event Next(1) 1368 | Next(1) 1369 | Intercepted event Completed 1370 | Completed 1371 | ``` 1372 | 1373 | 1374 | ## 条件和布尔操作(Conditional and Boolean Operators) 1375 | 1376 | 下面的操作符可用于根据条件发射或变换 Observables,或者对它们做布尔运算: 1377 | 1378 | 1379 | ### `takeUntil` 1380 | 1381 | 当第二个 Observable 发送数据之后,丢弃第一个 Observable 在这之后的所有消息。 1382 | 1383 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takeuntil.png) 1384 | 1385 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/takeuntil.html ) 1386 | 1387 | ```swift 1388 | example("takeUntil") { 1389 | let originalSequence = PublishSubject() 1390 | let whenThisSendsNextWorldStops = PublishSubject() 1391 | 1392 | _ = originalSequence 1393 | .takeUntil(whenThisSendsNextWorldStops) 1394 | .subscribe { 1395 | print($0) 1396 | } 1397 | 1398 | originalSequence.on(.Next(1)) 1399 | originalSequence.on(.Next(2)) 1400 | originalSequence.on(.Next(3)) 1401 | originalSequence.on(.Next(4)) 1402 | 1403 | whenThisSendsNextWorldStops.on(.Next(1)) 1404 | 1405 | originalSequence.on(.Next(5)) 1406 | } 1407 | ``` 1408 | 1409 | 运行结果: 1410 | 1411 | ``` 1412 | --- takeUntil example --- 1413 | Next(1) 1414 | Next(2) 1415 | Next(3) 1416 | Next(4) 1417 | Completed 1418 | ``` 1419 | 1420 | 1421 | ### `takeWhile` 1422 | 1423 | 发送原始 Observable 的数据,直到一个特定的条件为 false 1424 | 1425 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/takewhile.png) 1426 | 1427 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/takewhile.html ) 1428 | 1429 | ```swift 1430 | example("takeWhile") { 1431 | 1432 | let sequence = PublishSubject() 1433 | 1434 | _ = sequence 1435 | .takeWhile { int in 1436 | int < 4 1437 | } 1438 | .subscribe { 1439 | print($0) 1440 | } 1441 | 1442 | sequence.on(.Next(1)) 1443 | sequence.on(.Next(2)) 1444 | sequence.on(.Next(3)) 1445 | sequence.on(.Next(4)) 1446 | sequence.on(.Next(5)) 1447 | } 1448 | ``` 1449 | 1450 | 运行结果: 1451 | 1452 | ``` 1453 | --- takeWhile example --- 1454 | Next(1) 1455 | Next(2) 1456 | Next(3) 1457 | Completed 1458 | ``` 1459 | 1460 | 1461 | ## 算数和聚合(Mathematical and Aggregate Operators) 1462 | 1463 | ### `concat` 1464 | 1465 | 合并两个或者以上的 Observable 的消息,并且这些消息的发送时间不会交叉。(队列先后顺序不会交叉) 1466 | 1467 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/concat.png) 1468 | 1469 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/concat.html ) 1470 | 1471 | ```swift 1472 | example("concat") { 1473 | let var1 = BehaviorSubject(value: 0) 1474 | let var2 = BehaviorSubject(value: 200) 1475 | 1476 | // var3 is like an Observable> 1477 | let var3 = BehaviorSubject(value: var1) 1478 | 1479 | let d = var3 1480 | .concat() 1481 | .subscribe { 1482 | print($0) 1483 | } 1484 | 1485 | var1.on(.Next(1)) 1486 | var1.on(.Next(2)) 1487 | var1.on(.Next(3)) 1488 | var1.on(.Next(4)) 1489 | 1490 | var3.on(.Next(var2)) 1491 | 1492 | var2.on(.Next(201)) 1493 | 1494 | var1.on(.Next(5)) 1495 | var1.on(.Next(6)) 1496 | var1.on(.Next(7)) 1497 | var1.on(.Completed) 1498 | 1499 | var2.on(.Next(202)) 1500 | var2.on(.Next(203)) 1501 | var2.on(.Next(204)) 1502 | } 1503 | ``` 1504 | 1505 | 运行结果: 1506 | 1507 | ``` 1508 | --- concat example --- 1509 | Next(0) 1510 | Next(1) 1511 | Next(2) 1512 | Next(3) 1513 | Next(4) 1514 | Next(5) 1515 | Next(6) 1516 | Next(7) 1517 | Next(201) 1518 | Next(202) 1519 | Next(203) 1520 | Next(204) 1521 | ``` 1522 | 1523 | ### `reduce` 1524 | 1525 | 按顺序对Observable发射的每项数据应用一个函数并发射最终的值。 1526 | `Reduce` 操作符对原始 Observable 发射数据的第一项应用一个函数,然后再将这个函数的返回值与第二项数据一起传递给函数,以此类推,持续这个过程知道原始Observable发射它的最后一项数据并终止,此时 Reduce 返回的 Observable 发射这个函数返回的最终值。与数组序列的 `reduce` 操作类似。 1527 | 1528 | ![](https://raw.githubusercontent.com/kzaher/rxswiftcontent/master/MarbleDiagrams/png/reduce.png) 1529 | 1530 | [更多相关内容请查看 reactive.io]( http://reactivex.io/documentation/operators/reduce.html ) 1531 | 1532 | ```swift 1533 | example("reduce") { 1534 | _ = Observable.of(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 1535 | .reduce(0, accumulator: +) 1536 | .subscribe { 1537 | print($0) 1538 | } 1539 | } 1540 | ``` 1541 | 1542 | 运行结果: 1543 | 1544 | ``` 1545 | --- reduce example --- 1546 | Next(45) 1547 | Completed 1548 | ``` 1549 | --------------------------------------------------------------------------------