Swift进阶之RxSwift(一)

前言

  • 本文系RxSwift基础用法学习,适用于已经掌握swift基础的programmer。
  • RxSwift常作为MVVM的开发工具,如果对MVVM不熟悉的,建议先学习!当然两者也可以一起学习!推荐干货集中营-ReactiveCocoa+RXSwift+MVVM.
  • 官网学习地址
  • 本文系本人学习笔记,如有失误,欢迎各位大神指正!
  • 文章结尾有demo,demo中的登录模块使用的是MVVM模式,欢迎交流!

步入正题

0.为什么学习RxSwift

编程过程中有很多代码是关于事件响应的,当用户操作控制器时,我们需要通过Action来响应事件,通过通知来监测键盘高度,通过闭包来执行网络请求的响应,通过KVO来监测值的改变,如果有一样工具可以实现以上所有功能,那么RxSwift就是了!

RxSwift是ReactiveX在swift上的实现,在Java,C#,.net等语言和平台上都可以找到他的身影,所以就出现了这样一件有意思的事情,当你遇到问题时,或许在其他语言平台上可以找到你想要的答案。

举个🌰:在编码时我们需要很多耦合事件,把事件之间的耦合比作网络连接,以前我们需要冗长的网线来连接,有了RxSwift,你就可以使用WiFi了!

1.创建和订阅可观测序列

RxSwift中的核心类就是Observable,它就像一个路由器一样把事件转换成信号发给订阅者!其实现思路类似于通知,但通知属于其子集。

  • empty
/// 创建一个销毁包
let disposeBag = DisposeBag()
/// 创建一个空的可观测序列
let emptyObservable = Observable<Any>.empty()
/// 订阅空的观察者
emptyObservable.subscribe { event in
            print("empty")
 }.disposed(by: disposeBag)

先看disposeBag它的作用是用来销毁无用的可观测序列,emptyObserable是一个空的可观测序列,当某个事件发生时,但订阅者不需要知道发生了什么时,我们就可以使用发送一个空信号来告知订阅者。之后就是订阅了,订阅之后就可以拿到观察序列发出的信号,但这里的观测序列所携带的事件为空,所以event也为空,下面来看带信号的观测序列。

  • just
/// 创建单个元素/事件的可观测序列
Observable.just("🔴")
        .subscribe { event in
            print(event)
        }
        .disposed(by: disposeBag)
/// 打印结果:🔴

这里创建的是只包含单个元素的可观测序列,这里的元素可以是我们常用的数据类型,也可以是对象等。在订阅之后即可拿到事件或数据!

  • of
/// 创建包含多个元素的可观测序列
Observable.of("🐶", "🐱", "🐭", "🐹")
        .subscribe(onNext: { element in
            print(element)
        })
        .disposed(by: disposeBag)
/// 打印结果:
🐶
🐱
🐭
🐹

当一个事件存在多个参数时,我们可以使用此方法

  • from
/// 创建包含一个集合的可观测序列,集合可以是Array,Dictionary,Set
Observable.from(["🐶", "🐱", "🐭", "🐹"])
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
/// 打印结果:
🐶
🐱
🐭
🐹

上面几个方法只是简单的实现了信号/事件流的发送与订阅,但是在实际使用使用过程中往往需要自己来定制可观测序列。

  • create/custom
///通过传入的元素来创建可观测序列
let myJust = { (element: String) -> Observable<String> in
        return Observable.create { observer in
            observer.on(.next(element))
            observer.on(.completed)
            return Disposables.create()
        }
    }
/// 创建一个包含 🔴 的可观测序列
let newObserver = myJust("🔴")
/// 订阅观测序列
newObserver.subscribe { print($0) }.disposed(by: disposeBag)

如果理解了上面的例子以后,这个也定不成问题了!


然后还有几个方法

  • never
/// 创建一个永远不会执行的序列,不知道有什么用!
Observable<String>.never().subscribe { _ in
            print("This will never be printed")
    }
  • error
/// 创建一个序列,没有事件,而是error,且立即停止执行
Observable<Int>.error(TestError.test)
        .subscribe { print($0) }
        .disposed(by: disposeBag)
  • range
/// 创建一个序列,发送范围内integer类型数据
Observable.range(start: 1, count: 10)
        .subscribe { print($0) }
        .disposed(by: disposeBag)
  • repeatElement
/// 创建一个序列,发送已给定的元素,take的参数表示repead的次数
Observable.repeatElement("🔴")
        .take(3)
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
  • generate
/// 创建一个序列,当给出的条件为真时,会一直发送信号
Observable.generate(
            initialState: 0,
            condition: { $0 < 3 },
            iterate: { $0 + 1 }
        )
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
  • deferred
/// 创建一个序列,为每一个订阅者都提供一个新的序列,为了保证订阅者拿到的是最新的数据时,可以使用此方法
var count = 1
    
    let deferredSequence = Observable<String>.deferred {
        print("Creating \(count)")
        count += 1
        
        return Observable.create { observer in
            print("Emitting...")
            observer.onNext("🐶")
            observer.onNext("🐱")
            observer.onNext("🐵")
            return Disposables.create()
        }
    }
    
    deferredSequence
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)
    
    deferredSequence
        .subscribe(onNext: { print($0) })
        .disposed(by: disposeBag)

** 小结:Observable是一个比较抽象的类,RxSwift中提供了多样的方法来最大程度的方便使用,大家也可根据自己的实际情况来灵活应用!另外在实际情况中我们往往是希望全面掌控事件的发送与接收,下面的Subjects即可实现我们的需求。**

2.使用Subjects来工作

下面提到的subjects都是Observable的子类,相对于Observable,subject使用起来更加灵活,它既可以作为订阅者,也可以作为观测序列,因而能够多次订阅以及发送新的事件。

  • 先来个扩展方法,方便下文使用,这个方法实现了对subject的订阅,同时打印出发送的事件,参数id是一个标识符
/**
     Add observer with `id` and print each emitted event.
     - parameter id: an identifier for the subscription.
     */
    func addObserver(_ id: String) -> Disposable {
        return subscribe { print("Subscription:", id, "Event:", $0) }
    }
  • PublishSubject
    向所有订阅者广播最新事件
/// method 1
/// 创建销毁包
let disposeBag = DisposeBag()
/// 创建subject
let subject = PublishSubject<String>()
/// 实现订阅,下面订阅方法二选一,订阅需要在发送信号之前实现,对应MVVM中一个思路:在拿到数据之前就要实现拿到数据之后的操作
subject.addObserver("1").disposed(by: disposeBag) // 上文中封装的订阅
subject.subscribe { print($0) }.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
    向订阅者发送指定数量的事件,意思就是从最近发送的事件开始以0算起,逆序发送之前发送过的事件
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2)
/// 订阅者1
subject.addObserver("1").disposed(by: disposeBag)
subject.onNext("lol")
subject.onNext("🐶")
subject.onNext("🐱")
/// 订阅者2  
subject.addObserver("2").disposed(by: disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
/// 打印结果
--- ReplaySubject example ---
Subscription: 1 Event: next(lol)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐶)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
  • BehaviorSubject
    向所有订阅者广播事件,先最新的订阅者发送最新事件,使用方法与PublishSubject很相似
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
    Variable是对BehaviorSubject的封装,所以它可以向订阅者们发送最新的值,而且可以维持值的状态,它不会发送error,但是发生错误是会发送comepleted事件并结束。
let disposeBag = DisposeBag()
let variable = Variable("🔴")
/// 订阅者1
variable.asObservable().addObserver("1").disposed(by: disposeBag)
variable.value = "🐶"
variable.value = "🐱"
/// 订阅者2
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

** 掌握了以上的方法,基本就可以愉快的发送,订阅事件了,上手MVVM也不会有什么大问题!**

3. 关联文章

Swift进阶之RxSwift(二)
Swift进阶之RxSwift(三)
Swift进阶之RxSwift(四)

Demo地址,个人水平有限,如有问题,欢迎指出!


** 如果觉的本文有用的话,动动小手,点个赞!有问题可以在下方留言!**

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

推荐阅读更多精彩内容