Swift - RxSwift的使用詳解17(特征序列1:Single、Completable、Maybe)

通過之前的一系列文章,關于可被觀察的序列(Observable)我們應該都了解的查不多了。 除了ObservableRxSwift 還為我們提供了一些特征序列(Traits):SingleCompletableMaybeDriverControlEvent

我們可以將這些 Traits 看作是 Observable 的另外一個版本。它們之間的區別是:

  • Observable 是能夠用于任何上下文環境的通用序列。
  • Traits 可以幫助我們更準確的描述序列。同時它們還為我們提供上下文含義、語法糖,讓我們能夠用更加優雅的方式書寫代碼。

一、Single

1,基本介紹

SingleObservable 的另外一個版本。但它不像 Observable 可以發出多個元素,它要么只能發出一個元素,要么產生一個 error 事件。

  • 發出一個元素,或一個 error 事件
  • 不會共享狀態變化

2,應用場景

Single 比較常見的例子就是執行 HTTP 請求,然后返回一個應答或錯誤。不過我們也可以用 Single 來描述任何只有一個元素的序列。

3,SingleEvent

為方便使用,RxSwift 還為 Single 訂閱提供了一個枚舉(SingleEvent):

  • .success:里面包含該Single的一個元素值
  • .error:用于包含錯誤
public enum SingleEvent<Element> {
    case success(Element)
    case error(Swift.Error)
}

4,使用樣例

(1)創建 Single 和創建 Observable 非常相似。下面代碼我們定義一個用于生成網絡請求 Single 的函數:

//獲取豆瓣某頻道下的歌曲信息
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() }
    }
}
 
//與數據相關的錯誤類型
enum DataError: Error {
    case cantParseJSON
}

(2)接著我們可以使用如下方式使用這個 Single

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        //獲取第0個頻道的歌曲信息
        getPlaylist("0")
            .subscribe { event in
                switch event {
                case .success(let json):
                    print("JSON結果: ", json)
                case .error(let error):
                    print("發生錯誤: ", error)
                }
            }
            .disposed(by: disposeBag)
    }
}

(3)也可以使用 subscribe(onSuccess:onError:)這種方式:

import UIKit
import RxSwift
import RxCocoa
 
class ViewController: UIViewController {
    let disposeBag = DisposeBag()
     
    override func viewDidLoad() {
        //獲取第0個頻道的歌曲信息
        getPlaylist("0")
            .subscribe(onSuccess: { json in
                print("JSON結果: ", json)
            }, onError: { error in
                print("發生錯誤: ", error)
            })
            .disposed(by: disposeBag)
    }
}

(4)運行結果如下:

5,asSingle()

(1)我們可以通過調用 Observable 序列的.asSingle()方法,將它轉換為 Single

let disposeBag = DisposeBag()
 
Observable.of("1")
    .asSingle()
    .subscribe({ print($0) })
    .disposed(by: disposeBag)

(2)運行結果如下:

二、Completable

1,基本介紹

CompletableObservable 的另外一個版本。不像 Observable 可以發出多個元素,它要么只能產生一個 completed 事件,要么產生一個 error 事件。

  • 不會發出任何元素
  • 只會發出一個 completed 事件或者一個 error 事件
  • 不會共享狀態變化

2,應用場景

CompletableObservable<Void> 有點類似。適用于那些只關心任務是否完成,而不需要在意任務返回值的情況。比如:在程序退出時將一些數據緩存到本地文件,供下次啟動時加載。像這種情況我們只關心緩存是否成功。

3,CompletableEvent

為方便使用,RxSwiftCompletable 訂閱提供了一個枚舉(CompletableEvent):

  • .completed:用于產生完成事件
  • .error:用于產生一個錯誤
public enum CompletableEvent {
    case error(Swift.Error)
    case completed
}

4,使用樣例

(1)創建 Completable 和創建 Observable 非常相似。下面代碼我們使用 Completable 來模擬一個數據緩存本地的操作:

//將數據緩存到本地
func cacheLocally() -> Completable {
    return Completable.create { completable in
        //將數據緩存到本地(這里掠過具體的業務代碼,隨機成功或失敗)
        let success = (arc4random() % 2 == 0)
         
        guard success else {
            completable(.error(CacheError.failedCaching))
            return Disposables.create {}
        }
         
        completable(.completed)
        return Disposables.create {}
    }
}
 
//與緩存相關的錯誤類型
enum CacheError: Error {
    case failedCaching
}

(2)接著我們可以使用如下方式使用這個 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)運行結果如下(失敗的情況):

三、Maybe

1,基本介紹

Maybe 同樣是 Observable 的另外一個版本。它介于 SingleCompletable 之間,它要么只能發出一個元素,要么產生一個 completed 事件,要么產生一個 error 事件。

  • 發出一個元素、或者一個 completed 事件、或者一個 error 事件
  • 不會共享狀態變化

2,應用場景

Maybe 適合那種可能需要發出一個元素,又可能不需要發出的情況。

3,MaybeEvent

為方便使用,RxSwiftMaybe 訂閱提供了一個枚舉(MaybeEvent):

  • .success:里包含該 Maybe 的一個元素值
  • .completed:用于產生完成事件
  • .error:用于產生一個錯誤
public enum MaybeEvent<Element> {
    case success(Element)
    case error(Swift.Error)
    case completed
}

4,使用樣例

(1)創建 Maybe 和創建 Observable 同樣非常相似:

func generateString() -> Maybe<String> {
    return Maybe<String>.create { maybe in
         
        //成功并發出一個元素
        maybe(.success("hangge.com"))
         
        //成功但不發出任何元素
        maybe(.completed)
         
        //失敗
        //maybe(.error(StringError.failedGenerate))
         
        return Disposables.create {}
    }
}
 
//與緩存相關的錯誤類型
enum StringError: Error {
    case failedGenerate
}

(2)接著我們可以使用如下方式使用這個 Maybe

generateString()
    .subscribe { maybe in
        switch maybe {
        case .success(let element):
            print("執行完畢,并獲得元素:\(element)")
        case .completed:
            print("執行完畢,且沒有任何元素。")
        case .error(let error):
            print("執行失敗: \(error.localizedDescription)")
   
        }
    }
    .disposed(by: disposeBag)

(3)也可以使用 subscribe(onSuccess:onCompleted:onError:) 這種方式:

generateString()
    .subscribe(onSuccess: { element in
        print("執行完畢,并獲得元素:\(element)")
    },
               onError: { error in
                print("執行失敗: \(error.localizedDescription)")
    },
               onCompleted: {
                print("執行完畢,且沒有任何元素。")
    })
    .disposed(by: disposeBag)

(4)運行結果如下:

5,asMaybe()

(1)我們可以通過調用 Observable 序列的 .asMaybe()方法,將它轉換為 Maybe

let disposeBag = DisposeBag()
 
Observable.of("1")
    .asMaybe()
    .subscribe({ print($0) })
    .disposed(by: disposeBag)

(2)運行結果如下:

RxSwift使用詳解系列
原文出自:www.hangge.com轉載請保留原文鏈接

?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容