Learn to code with RxSwift

  • 首先,何为RxSwift?

RxSwiftReactiveXSwift版本,一个响应式变成框架。传送门

  • 开始之前,先介绍两个function,并没有什么实质性作用,只是为了方便学习演示

/**
 延迟`delay`时长之后执行`closure`闭包
 - parameter delay: 闭包延迟执行时间
 - parameter closure: 返回值`Void`的闭包
 */
public func delay(_ delay: Double, closure: @escaping (Swift.Void) -> Swift.Void)
/**
 起到一个分割线作用
 - parameter description: example 简介
 - parameter action: 返回值`Void`的闭包
 */
public func example(_ description: String, action: (Swift.Void) -> Swift.Void)
  • RxSwift基础

Observable: Observable是观察着模式中的被观察对象,相当于一个事件序列GeneratorType,它会向它的订阅者发送事件信息,

  • next() :一个新的事件
  • complete() :完成事件
  • error() : 错误事件

多数情况都是对不同的Observable进行subscribe操作,并在接收到事件后进行相应的操作


  • 名词解释

  • DisposeBag

相当于一个autoreleasepool(自动释放池),对观察者进行管理,在适当的时候销毁观察者

  • Observable

Observables will not execute their subscription closure unless there is a subscriber
Observables只有被订阅之后才会被执行,否则不予执行

```

example("一个未被订阅的Observable") {
_ = Observable<String>.create { observerOfString -> Disposable in
print("This will never be printed")
observerOfString.on(.next("😬"))
observerOfString.on(.completed)
return Disposables.create()
}
}
//不会打印任何数据,因为该Observable没有被订阅

- ###### subscribe
> subscribe是订阅`sequence`发出的事件,比如`next`事件,`error`事件等。而`subscribe(onNext:)`是监听`sequence`发出的`next`事件中的`element`进行处理,他会忽略`error`和`completed`事件。相对应的还有`subscribe(onError:) `和 `subscribe(onCompleted:)`

   ```
example("被订阅的Observable") {
     let disposeBag = DisposeBag()
     Observable<String>.create { observerOfString in
       print("Observable created")
       observerOfString.on(.next("😉"))
       observerOfString.on(.completed)
       return Disposables.create()
       }
       .subscribe { event in
           print(event)
       }.addDisposableTo(disposeBag)
}
执行结果:
--- 被订阅的Observable ---
Observable created
next(😉)
completed

  • Creating and Subscribing to Observables/ 创建并订阅Observables

  • never 创建一个空序列,不发送任何事件
example("never") {
    let disposeBag = DisposeBag()
    let neverSequence = Observable<String>.never()
    neverSequence
        .subscribe { _ in
            print("This will never be printed")
    }
    .addDisposableTo(disposeBag)
}
  • empty 一个空的序列,它只发送 .Completed 消息
example("empty") {
    let disposeBag = DisposeBag()
        Observable<Int>.empty()
        .subscribe { event in
            print(event)
        }
        .disposed(by: disposeBag)
}
//执行结果:
--- empty example ---
completed
  • just 只包含一个元素的序列,发送一个next事件和completed事件
    example("just") {
    let disposeBag = DisposeBag()
    Observable.just("🔴")
        .subscribe { event in
            print(event)
        }
        .disposed(by: disposeBag)
}
//执行结果:
--- just example ---
next(🔴)
completed
  • of 将所有元素依次转换为序列发送
example("of") {
    let disposeBag = DisposeBag()
    Observable.of("🐶", "🐱", "🐭", "🐹")
        .subscribe(onNext: { element in
            print(element)
        })
        .disposed(by: disposeBag)
}
//执行结果
--- of example ---
🐶
🐱
🐭
🐹
  • from 从数组或字典或集合的所有元素创建序列发送
example("from") {
    let disposeBag = DisposeBag()
        Observable.from(["🐶", "🐱", "🐭", "🐹"])
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
}
//执行结果
--- from example ---
🐶
🐱
🐭
🐹
  • create 创建一个自定义Observable
example("create") {
    let disposeBag = DisposeBag()
    
    let myJust = { (element: String) -> Observable<String> in
        return Observable.create { observer in
            observer.on(.next(element))
            observer.on(.completed)
            return Disposables.create()
        }
    }
    myJust("🔴")
        .subscribe { print($0) }
        .disposed(by: disposeBag)
}
//执行结果:
--- create example ---
next(🔴)
completed
  • error 创建一个只发送error事件的Observable
example("error") {
    let disposeBag = DisposeBag()
    Observable<Int>.error(TestError.test)
        .subscribe { print($0) }
        .disposed(by: disposeBag)
}
//执行结果:
--- error example ---
error(test)

  • Subject

Subject可以订阅别的Observable,也可以被订阅并给它的订阅者发送事件
常用:

  1. PublishSubject
  2. ReplaySubject
  3. BehaviorSubject
  4. Variable
  • PublishSubject 它的订阅者只能接收到订阅后发送的事件,无法接收到订阅之前的事件
example("PublishSubject") {
      let disposeBag = DisposeBag()
      let subject = PublishSubject<String>()
      subject.addObserver("1").disposed(by: disposeBag)
      subject.onNext("🐶")
      subject.onNext("🐱")
      subject.addObserver("2").disposed(by: disposeBag)
      subject.onNext("🅰️")
      subject.onNext("🅱️")
}
//执行结果:
--- PublishSubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
  • ReplaySubject 它的订阅者定接收到订阅之后发出的事件,并且能接收到订阅之前的信号,至于能接收到订阅之前的多少个信号则由 bufferSize 参数决定
example("ReplaySubject") {
      let disposeBag = DisposeBag()
      let subject = ReplaySubject<String>.create(bufferSize: 1)
      subject.addObserver("1").disposed(by: disposeBag)
      subject.onNext("🐶")
      subject.onNext("🐱")
      subject.addObserver("2").disposed(by: disposeBag)
      subject.onNext("🅰️")
      subject.onNext("🅱️")
}
//执行结果:
--- ReplaySubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
  • BehaviorSubject 它的订阅者定接收到订阅之后发出的事件,并且能接收到订阅之前的前一个信号
example("BehaviorSubject") {
      let disposeBag = DisposeBag()
      let subject = BehaviorSubject(value: "🔴")
      subject.addObserver("1").disposed(by: disposeBag)
      subject.onNext("🐶")
      subject.onNext("🐱")
      subject.addObserver("2").disposed(by: disposeBag)
      subject.onNext("🅰️")
      subject.onNext("🅱️")
      subject.addObserver("3").disposed(by: disposeBag)
      subject.onNext("🍐")
      subject.onNext("🍊")
}
//执行结果:
--- BehaviorSubject example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 3 Event: next(🅱️)
Subscription: 1 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 2 Event: next(🍊)
Subscription: 3 Event: next(🍊)
  • Variable 它的订阅者定接收到订阅之后发出的事件和订阅之前的前一个信号,并且当它的 value 发生改变时所有的订阅者能收到事件,完成后向所有订阅者发送 complete 事件
example("Variable") {
      let disposeBag = DisposeBag()
      let variable = Variable("🔴")
      variable.asObservable().addObserver("1").disposed(by: disposeBag)
      variable.value = "🐶"
      variable.value = "🐱"
      variable.asObservable().addObserver("2").disposed(by: disposeBag)
      variable.value = "🅰️"
      variable.value = "🅱️"
}
//执行结果:
--- Variable example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 1 Event: completed
Subscription: 2 Event: completed

  • 组合操作

  • 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
🐶
🐱
🐭
🐹
  • merge 把两个队列按照顺序组合在一起
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 将多个序列组合在一起,当所有序列能凑成一组(一一对应)时才发送事件
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
  • combineLatest 多个序列合并,每个序列的最新值进行组合
example("combineLatest") {
      let disposeBag = DisposeBag()
      let stringSubject = PublishSubject<String>()
      let intSubject = PublishSubject<Int>()
      Observable.combineLatest(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("🆎")
}
//执行结果:
--- combineLatest example ---
🅱️ 1
🅱️ 2
🆎 2

  • 转换操作

  • map 对序列的值做转换操作后返回,序列的值发生改变
example("map") {
      let disposeBag = DisposeBag()
      Observable.of(1, 2, 3)
          .map { $0 * $0 }   //1*1 2*2 3*3
          .subscribe(onNext: { print($0) })
          .disposed(by: disposeBag)
}
//执行结果:
--- map example ---
1
4
9
  • flatMap and flatMapLatest 看代码
example("flatMap and flatMapLatest") {
    let disposeBag = DisposeBag()
    struct Player {
        var score: Variable<Int>
    }
    let 👦🏻 = Player(score: Variable(80))
    let 👧🏼 = Player(score: Variable(90))
    let player = Variable(👦🏻)
    player.asObservable()
        .flatMap { $0.score.asObservable() } // Change flatMap to flatMapLatest and observe change in printed output
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
    👦🏻.score.value = 85
    player.value = 👧🏼
    👦🏻.score.value = 95 // Will be printed when using flatMap, but will not be printed when using flatMapLatest
    👧🏼.score.value = 100
}
//执行结果:
--- flatMap and flatMapLatest example ---
80
85
90
95
100
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 发现 关注 消息 RxSwift入坑解读-你所需要知道的各种概念 沸沸腾关注 2016.11.27 19:11*字...
    枫叶1234阅读 2,780评论 0 2
  • 本文章内部分图片资源来自RayWenderlich.com 本文结合自己的理解来总结介绍一下RxSwift最基本的...
    FKSky阅读 2,853评论 4 14
  • 最近在学习RxSwift相关的内容,在这里记录一些基本的知识点,以便今后查阅。 Observable 在RxSwi...
    L_Zephyr阅读 1,739评论 1 4
  • //PublishSubject -> 会发送订阅者从订阅之后的事件序列 PublishSubjectlet se...
    zidon阅读 1,560评论 0 3
  • 《老井》 文/蛟龙 习惯性的翻阅 喜爱的文字 不同的个性,审美,情趣 不同的阅读爱好 众口难调 我喜欢来自山林,狂...
    F芳子阅读 434评论 0 0