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

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

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

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

一、Single

1,基本介紹

SingleObservable 的另外一個(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,基本介紹

CompletableObservable 的另外一個(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)景

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

3,CompletableEvent

為方便使用,RxSwiftCompletable 訂閱提供了一個(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è)版本。它介于 SingleCompletable 之間,它要么只能發(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

為方便使用,RxSwiftMaybe 訂閱提供了一個(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é)果如下:

RxSwift使用詳解系列
原文出自:www.hangge.com轉(zhuǎn)載請(qǐng)保留原文鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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