RxSwift的使用(二)

RxSwift 核心內(nèi)容

image
  • Observable - 產(chǎn)生事件
  • Observer - 響應(yīng)事件
  • Operator - 創(chuàng)建變化組合事件
  • Disposable - 管理綁定(訂閱)的生命周期
  • Schedulers - 線程隊(duì)列調(diào)配
1.0桑驱、 Observable - 可監(jiān)聽序列

所有的實(shí)物都是序列

/** Observable 可以用于描述元素異步產(chǎn)生的序列*/

Observable<Double>  // 溫度,把溫度看作是一個(gè)序列

Observable<JSON>    //JSON,把網(wǎng)絡(luò)請(qǐng)求的返回的 JSON 看作是一個(gè)序列

Observable<Void>    //任務(wù)回調(diào),把任務(wù)回調(diào)看作是一個(gè)序列

/**框架已經(jīng)幫我們創(chuàng)建好了許多常用的序列启盛。
例如:button的點(diǎn)擊走孽,textField的當(dāng)前文本焙格,switch的開關(guān)狀態(tài)载佳,slider的當(dāng)前數(shù)值等等演顾,而另外一些重抖,則需要我們自己創(chuàng)建*/

//自定義的序列
let numbers: Observable<Int> = Observable.create { observer -> Disposable in

    observer.onNext(0)
    observer.onNext(1)
    observer.onNext(2)
    observer.onNext(3)
    observer.onNext(4)
    observer.onNext(5)
    observer.onNext(6)
    observer.onNext(7)
    observer.onNext(8)
    observer.onNext(9)
    observer.onCompleted()

    return Disposables.create()
}
1.1楚午、在閉包回調(diào)中的使用
typealias JSON = Any

let json: Observable<JSON> = Observable.create { (observer) -> Disposable in

    let task = URLSession.shared.dataTask(with: ...) { data, _, error in

        guard error == nil else {
            observer.onError(error!)
            return
        }

        guard let data = data,
            let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
            else {
            observer.onError(DataError.cantParseJSON)
            return
        }

        observer.onNext(jsonObject)
        observer.onCompleted()
    }

    task.resume()

    return Disposables.create { task.cancel() }
}

json
    .subscribe(onNext: { json in
        print("取得 json 成功: \(json)")
    }, onError: { error in
        print("取得 json 失敗 Error: \(error.localizedDescription)")
    }, onCompleted: {
        print("取得 json 任務(wù)成功完成")
    })
    .disposed(by: disposeBag)
2.0宴偿、Observer - 觀察者

觀察者 是用來(lái)監(jiān)聽事件湘捎,然后它需要這個(gè)事件做出響應(yīng)。例如:彈出提示框就是觀察者窄刘,它對(duì)點(diǎn)擊按鈕這個(gè)事件做出響應(yīng)

Observer<Double>
Observer<JSON>
Observer<Void>
2.1窥妇、創(chuàng)建觀察者
/**框架已經(jīng)幫我們創(chuàng)建好了許多常用的觀察者。例如:view 是否隱藏娩践,button 是否可點(diǎn)擊活翩, label 的當(dāng)前文本,imageView 的當(dāng)前圖片等等翻伺,而另外一些也要我們自己創(chuàng)建*/

//自定義觀察者
tap.subscribe(onNext: { [weak self] in
    self?.showAlert()
}, onError: { error in
    print("發(fā)生錯(cuò)誤: \(error.localizedDescription)")
}, onCompleted: {
    print("任務(wù)完成")
})
3.0材泄、即是可監(jiān)聽序列,又是觀察者
/**例如:textField的當(dāng)前文本吨岭。它可以看成是由用戶輸入拉宗,而產(chǎn)生的一個(gè)文本序列*/

// 作為可監(jiān)聽序列
let observable = textField.rx.text
observable.subscribe(onNext: { text in show(text: text) })

// 作為觀察者
let observer = textField.rx.text
let text: Observable<String?> = ...
text.bind(to: observer)
3.1、框架中定義的其他即可以是觀察者辣辫,又可以是監(jiān)聽序列的輔助類型
  • AsyncSubject
  • PublishSubject
  • ReplaySubject
  • BehaviorSubject
  • ControlProperty
4.0旦事、Operator - 操作符

Operator - 操作符

image

操作符可以幫助大家創(chuàng)建新的序列,或者變化組合原有的序列急灭,從而生成一個(gè)新的序列姐浮。

filter - 過(guò)濾

image

map - 轉(zhuǎn)換

image

zip - 配對(duì)

image
4.1、操作符的使用
// 溫度
let rxTemperature: Observable<Double> = ...

// filter 操作符
rxTemperature.filter { temperature in temperature > 33 }
    .subscribe(onNext: { temperature in
        print("高溫:\(temperature)度")
    })
    .disposed(by: disposeBag)
// JSON
let json: Observable<JSON> = ...

// map 操作符
json.map(Model.init)
    .subscribe(onNext: { model in
        print("取得 Model: \(model)")
    })
    .disposed(by: disposeBag)
// 漢堡
let rxHamburg: Observable<Hamburg> = ...
// 薯?xiàng)l
let rxFrenchFries: Observable<FrenchFries> = ...

// zip 操作符
Observable.zip(rxHamburg, rxFrenchFries)
    .subscribe(onNext: { (hamburg, frenchFries) in
        print("取得漢堡: \(hamburg) 和薯?xiàng)l:\(frenchFries)")
    })
    .disposed(by: disposeBag)
5.0化戳、Disposable - 可被清除的資源
image
var disposable: Disposable?

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.disposable = textField.rx.text.orEmpty
        .subscribe(onNext: { text in print(text) })
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    self.disposable?.dispose()
}
5.1单料、DisposeBag - 清除包
image
var disposeBag = DisposeBag()

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    textField.rx.text.orEmpty
        .subscribe(onNext: { text in print(text) })
        .disposed(by: self.disposeBag)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    self.disposeBag = DisposeBag()
}

5.2埋凯、takeUntil - 自動(dòng)取消訂閱

override func viewDidLoad() {
    super.viewDidLoad()

    ...

    _ = usernameValid
        .takeUntil(self.rx.deallocated)
        .bind(to: passwordOutlet.rx.isEnabled)

    _ = usernameValid
        .takeUntil(self.rx.deallocated)
        .bind(to: usernameValidOutlet.rx.isHidden)

    _ = passwordValid
        .takeUntil(self.rx.deallocated)
        .bind(to: passwordValidOutlet.rx.isHidden)

    _ = everythingValid
        .takeUntil(self.rx.deallocated)
        .bind(to: doSomethingOutlet.rx.isEnabled)

    _ = doSomethingOutlet.rx.tap
        .takeUntil(self.rx.deallocated)
        .subscribe(onNext: { [weak self] in self?.showAlert() })
}
6.0、Schedulers - 調(diào)度器

Schedulers 是 Rx 實(shí)現(xiàn)多線程的核心模塊扫尖,它主要用于控制任務(wù)在哪個(gè)線程或隊(duì)列運(yùn)行白对。

//正常gcd,后臺(tái)取得數(shù)據(jù),主線程處理結(jié)果
DispatchQueue.global(qos: .userInitiated).async {
    let data = try? Data(contentsOf: url)
    DispatchQueue.main.async {
        self.data = data
    }
}

//RxSwift 來(lái)實(shí)現(xiàn)
let rxData: Observable<Data> = ...

rxData
    .subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
    .observeOn(MainScheduler.instance)
    .subscribe(onNext: { [weak self] data in
        self?.data = data
    })
    .disposed(by: disposeBag)

MainScheduler
MainScheduler 代表主線程换怖。如果你需要執(zhí)行一些和 UI 相關(guān)的任務(wù)甩恼,就需要切換到該 Scheduler 運(yùn)行。

SerialDispatchQueueScheduler
SerialDispatchQueueScheduler 抽象了串行 DispatchQueue沉颂。如果你需要執(zhí)行一些串行任務(wù)条摸,可以切換到這個(gè) Scheduler 運(yùn)行。

ConcurrentDispatchQueueScheduler
ConcurrentDispatchQueueScheduler 抽象了并行 DispatchQueue铸屉。如果你需要執(zhí)行一些并發(fā)任務(wù)钉蒲,可以切換到這個(gè) Scheduler 運(yùn)行。

OperationQueueScheduler
OperationQueueScheduler 抽象了 NSOperationQueue彻坛。
它具備 NSOperationQueue 的一些特點(diǎn)顷啼,例如,你可以通過(guò)設(shè)置 maxConcurrentOperationCount昌屉,來(lái)控制同時(shí)執(zhí)行并發(fā)任務(wù)的最大數(shù)量钙蒙。
7.0、Error Handling - 錯(cuò)誤處理

retry - 重試

// 請(qǐng)求 JSON 失敗時(shí)间驮,立即重試躬厌,
// 重試 3 次后仍然失敗,就將錯(cuò)誤拋出

let rxJson: Observable<JSON> = ...

rxJson
    .retry(3)
    .subscribe(onNext: { json in
        print("取得 JSON 成功: \(json)")
    }, onError: { error in
        print("取得 JSON 失敗: \(error)")
    })
    .disposed(by: disposeBag)

retryWhen - 重試延遲

RxSwift中文文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末竞帽,一起剝皮案震驚了整個(gè)濱河市扛施,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌屹篓,老刑警劉巖煮嫌,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異抱虐,居然都是意外死亡昌阿,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門恳邀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)懦冰,“玉大人,你說(shuō)我怎么就攤上這事谣沸∷⒏郑” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵乳附,是天一觀的道長(zhǎng)内地。 經(jīng)常有香客問我伴澄,道長(zhǎng),這世上最難降的妖魔是什么阱缓? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任非凌,我火速辦了婚禮,結(jié)果婚禮上荆针,老公的妹妹穿的比我還像新娘敞嗡。我一直安慰自己,他們只是感情好航背,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布喉悴。 她就那樣靜靜地躺著,像睡著了一般玖媚。 火紅的嫁衣襯著肌膚如雪箕肃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天今魔,我揣著相機(jī)與錄音突雪,去河邊找鬼。 笑死涡贱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惹想。 我是一名探鬼主播问词,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼嘀粱!你這毒婦竟也來(lái)了激挪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锋叨,失蹤者是張志新(化名)和其女友劉穎垄分,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娃磺,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄湿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了偷卧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豺瘤。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖听诸,靈堂內(nèi)的尸體忽然破棺而出坐求,到底是詐尸還是另有隱情,我是刑警寧澤晌梨,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布桥嗤,位于F島的核電站须妻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏泛领。R本人自食惡果不足惜荒吏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望师逸。 院中可真熱鬧司倚,春花似錦、人聲如沸篓像。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)员辩。三九已至盒粮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奠滑,已是汗流浹背丹皱。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宋税,地道東北人摊崭。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杰赛,于是被迫代替她去往敵國(guó)和親呢簸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 上一次咱們介紹了函數(shù)響應(yīng)式編程思想乏屯,并由此引出了咱們的RxSwift響應(yīng)式框架根时,在這篇文章中,我們簡(jiǎn)單介紹一下Rx...
    Daniel_Harvey閱讀 757評(píng)論 2 4
  • 內(nèi)容概覽: Rx Marble Diagrams(寶石圖) 關(guān)鍵概念 Event - 事件 Observable ...
    FicowShen閱讀 3,338評(píng)論 0 8
  • 一辰晕、Observable二蛤迎、Observer三、Subject四含友、Operator五替裆、Disposable六、Sc...
    yahibo閱讀 694評(píng)論 2 4
  • 一窘问、為什么要使用RxSwift扎唾? 因?yàn)槭褂肦xSwift框架我們可以使target-action、代理南缓、閉包回調(diào)胸遇、...
    無(wú)神閱讀 1,197評(píng)論 1 5
  • RxSwift核心 1. Observable - 可被監(jiān)聽的序列 Observable 可以用于描述元素異步產(chǎn)生...
    一生信仰閱讀 2,557評(píng)論 1 1