通過(guò)之前的一系列文章坎弯,關(guān)于可被觀察的序列(Observable
)我們應(yīng)該都了解的查不多了纺涤。 除了Observable
,RxSwift
還為我們提供了一些特征序列(Traits
):Single
抠忘、Completable
撩炊、Maybe
、Driver
崎脉、ControlEvent
拧咳。
我們可以將這些 Traits
看作是 Observable
的另外一個(gè)版本。它們之間的區(qū)別是:
-
Observable
是能夠用于任何上下文環(huán)境的通用序列囚灼。 - 而
Traits
可以幫助我們更準(zhǔn)確的描述序列骆膝。同時(shí)它們還為我們提供上下文含義、語(yǔ)法糖灶体,讓我們能夠用更加優(yōu)雅的方式書寫代碼阅签。
一、Single
1蝎抽,基本介紹
Single
是 Observable
的另外一個(gè)版本政钟。但它不像 Observable
可以發(fā)出多個(gè)元素,它要么只能發(fā)出一個(gè)元素樟结,要么產(chǎn)生一個(gè) error
事件养交。
- 發(fā)出一個(gè)元素,或一個(gè)
error
事件 - 不會(huì)共享狀態(tài)變化
2瓢宦,應(yīng)用場(chǎng)景
Single
比較常見(jiàn)的例子就是執(zhí)行 HTTP
請(qǐng)求碎连,然后返回一個(gè)應(yīng)答或錯(cuò)誤。不過(guò)我們也可以用 Single
來(lái)描述任何只有一個(gè)元素的序列刁笙。
3破花,SingleEvent
為方便使用,RxSwift
還為 Single
訂閱提供了一個(gè)枚舉(SingleEvent
):
-
.success
:里面包含該Single
的一個(gè)元素值 -
.error
:用于包含錯(cuò)誤
public enum SingleEvent<Element> {
case success(Element)
case error(Swift.Error)
}
4疲吸,使用樣例
(1)創(chuàng)建 Single
和創(chuàng)建 Observable
非常相似座每。下面代碼我們定義一個(gè)用于生成網(wǎng)絡(luò)請(qǐng)求 Single
的函數(shù):
//獲取豆瓣某頻道下的歌曲信息
func getPlaylist(_ channel: String) -> Single<[String: Any]> {
return Single<[String: Any]>.create { single in
let url = "https://douban.fm/j/mine/playlist?"
+ "type=n&channel=\(channel)&from=mainsite"
let task = URLSession.shared.dataTask(with: URL(string: url)!) { data, _, error in
if let error = error {
single(.error(error))
return
}
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data,
options: .mutableLeaves),
let result = json as? [String: Any] else {
single(.error(DataError.cantParseJSON))
return
}
single(.success(result))
}
task.resume()
return Disposables.create { task.cancel() }
}
}
//與數(shù)據(jù)相關(guān)的錯(cuò)誤類型
enum DataError: Error {
case cantParseJSON
}
(2)接著我們可以使用如下方式使用這個(gè) Single
:
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
//獲取第0個(gè)頻道的歌曲信息
getPlaylist("0")
.subscribe { event in
switch event {
case .success(let json):
print("JSON結(jié)果: ", json)
case .error(let error):
print("發(fā)生錯(cuò)誤: ", error)
}
}
.disposed(by: disposeBag)
}
}
(3)也可以使用 subscribe(onSuccess:onError:)
這種方式:
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
//獲取第0個(gè)頻道的歌曲信息
getPlaylist("0")
.subscribe(onSuccess: { json in
print("JSON結(jié)果: ", json)
}, onError: { error in
print("發(fā)生錯(cuò)誤: ", error)
})
.disposed(by: disposeBag)
}
}
(4)運(yùn)行結(jié)果如下:
5,asSingle()
(1)我們可以通過(guò)調(diào)用 Observable
序列的.asSingle()
方法摘悴,將它轉(zhuǎn)換為 Single
峭梳。
let disposeBag = DisposeBag()
Observable.of("1")
.asSingle()
.subscribe({ print($0) })
.disposed(by: disposeBag)
(2)運(yùn)行結(jié)果如下:
二、Completable
1蹂喻,基本介紹
Completable
是 Observable
的另外一個(gè)版本葱椭。不像 Observable
可以發(fā)出多個(gè)元素,它要么只能產(chǎn)生一個(gè) completed
事件口四,要么產(chǎn)生一個(gè) error 事件孵运。
- 不會(huì)發(fā)出任何元素
- 只會(huì)發(fā)出一個(gè)
completed
事件或者一個(gè)error
事件 - 不會(huì)共享狀態(tài)變化
2,應(yīng)用場(chǎng)景
Completable
和 Observable<Void>
有點(diǎn)類似蔓彩。適用于那些只關(guān)心任務(wù)是否完成治笨,而不需要在意任務(wù)返回值的情況。比如:在程序退出時(shí)將一些數(shù)據(jù)緩存到本地文件赤嚼,供下次啟動(dòng)時(shí)加載旷赖。像這種情況我們只關(guān)心緩存是否成功。
3更卒,CompletableEvent
為方便使用等孵,RxSwift
為 Completable
訂閱提供了一個(gè)枚舉(CompletableEvent
):
-
.completed
:用于產(chǎn)生完成事件 -
.error
:用于產(chǎn)生一個(gè)錯(cuò)誤
public enum CompletableEvent {
case error(Swift.Error)
case completed
}
4,使用樣例
(1)創(chuàng)建 Completable
和創(chuàng)建 Observable
非常相似蹂空。下面代碼我們使用 Completable
來(lái)模擬一個(gè)數(shù)據(jù)緩存本地的操作:
//將數(shù)據(jù)緩存到本地
func cacheLocally() -> Completable {
return Completable.create { completable in
//將數(shù)據(jù)緩存到本地(這里掠過(guò)具體的業(yè)務(wù)代碼俯萌,隨機(jī)成功或失敗)
let success = (arc4random() % 2 == 0)
guard success else {
completable(.error(CacheError.failedCaching))
return Disposables.create {}
}
completable(.completed)
return Disposables.create {}
}
}
//與緩存相關(guān)的錯(cuò)誤類型
enum CacheError: Error {
case failedCaching
}
(2)接著我們可以使用如下方式使用這個(gè) Completable
:
cacheLocally()
.subscribe { completable in
switch completable {
case .completed:
print("保存成功!")
case .error(let error):
print("保存失敗: \(error.localizedDescription)")
}
}
.disposed(by: disposeBag)
(3)也可以使用 subscribe(onCompleted:onError:)
這種方式:
cacheLocally()
.subscribe(onCompleted: {
print("保存成功!")
}, onError: { error in
print("保存失敗: \(error.localizedDescription)")
})
.disposed(by: disposeBag)
(4)運(yùn)行結(jié)果如下(失敗的情況):
三上枕、Maybe
1绳瘟,基本介紹
Maybe
同樣是 Observable
的另外一個(gè)版本。它介于 Single
和 Completable
之間姿骏,它要么只能發(fā)出一個(gè)元素糖声,要么產(chǎn)生一個(gè) completed
事件,要么產(chǎn)生一個(gè) error
事件分瘦。
- 發(fā)出一個(gè)元素蘸泻、或者一個(gè)
completed
事件、或者一個(gè)error
事件 - 不會(huì)共享狀態(tài)變化
2嘲玫,應(yīng)用場(chǎng)景
Maybe
適合那種可能需要發(fā)出一個(gè)元素悦施,又可能不需要發(fā)出的情況。
3去团,MaybeEvent
為方便使用抡诞,RxSwift
為 Maybe
訂閱提供了一個(gè)枚舉(MaybeEvent
):
-
.success
:里包含該Maybe
的一個(gè)元素值 -
.completed
:用于產(chǎn)生完成事件 -
.error
:用于產(chǎn)生一個(gè)錯(cuò)誤
public enum MaybeEvent<Element> {
case success(Element)
case error(Swift.Error)
case completed
}
4穷蛹,使用樣例
(1)創(chuàng)建 Maybe
和創(chuàng)建 Observable
同樣非常相似:
func generateString() -> Maybe<String> {
return Maybe<String>.create { maybe in
//成功并發(fā)出一個(gè)元素
maybe(.success("hangge.com"))
//成功但不發(fā)出任何元素
maybe(.completed)
//失敗
//maybe(.error(StringError.failedGenerate))
return Disposables.create {}
}
}
//與緩存相關(guān)的錯(cuò)誤類型
enum StringError: Error {
case failedGenerate
}
(2)接著我們可以使用如下方式使用這個(gè) Maybe
:
generateString()
.subscribe { maybe in
switch maybe {
case .success(let element):
print("執(zhí)行完畢,并獲得元素:\(element)")
case .completed:
print("執(zhí)行完畢昼汗,且沒(méi)有任何元素肴熏。")
case .error(let error):
print("執(zhí)行失敗: \(error.localizedDescription)")
}
}
.disposed(by: disposeBag)
(3)也可以使用 subscribe(onSuccess:onCompleted:onError:)
這種方式:
generateString()
.subscribe(onSuccess: { element in
print("執(zhí)行完畢,并獲得元素:\(element)")
},
onError: { error in
print("執(zhí)行失敗: \(error.localizedDescription)")
},
onCompleted: {
print("執(zhí)行完畢顷窒,且沒(méi)有任何元素蛙吏。")
})
.disposed(by: disposeBag)
(4)運(yùn)行結(jié)果如下:
5,asMaybe()
(1)我們可以通過(guò)調(diào)用 Observable
序列的 .asMaybe()
方法鞋吉,將它轉(zhuǎn)換為 Maybe
鸦做。
let disposeBag = DisposeBag()
Observable.of("1")
.asMaybe()
.subscribe({ print($0) })
.disposed(by: disposeBag)
(2)運(yùn)行結(jié)果如下: