95
67

More than 5 years have passed since last update.

RxSwift 3.3.0で追加された3つのUnit(Single, Maybe, Completable)

Last updated at Posted at 2017-03-15

RxSwift 3.3.0で3つのUnitが追加されました。

  • Single
  • Maybe
  • Completable

RxJavaにあったものが輸入された形のようです。

付属のPlaygroundに例が書かれていなかったので、ざっくりどんなものか確認してみました。
この記事は半分備忘録みたいなものになります。

追記

3.4.0で subscription closures (onSuccess, onError, onCompleted) が実装されました。
やっぱり欲しいよね。プルリク投げてくれたfreak4pcさんありがとう。

Add subscription closures for Single, Maybe and Completable (onSuccess, onError, onCompleted) by freak4pc · Pull Request #1175 · ReactiveX/RxSwift

概要

まず前提として、 ObservableCompleted あるいは Error が流れた時点でそれ以上何も流れなくなりますが、その2つが流れない限り Next は延々と流れてくる可能性があります。

それを踏まえて今回追加された3つのUnitについて見てみると、以下の表のようになります。

Single Maybe Completable
Success ×
Completed ×
Error

Success は 1回だけ流れる Next だと思って下さい。
そのSuccess が流れるのが SingleMaybe です。
MaybeSuccess が流れず、 Completed のみ流れてくる可能性があります。
Completable では Success は流れてきません。

それぞれつくって、実際にどんな風に使えるのか見ていきましょう。

Single

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .do(onNext: { (value) in
        print("onNext")
    }, onError: { (error) in
        print("onError")
    }, onCompleted: {
        print("onCompleted")
    }, onSubscribe: {
        // subscribe前に実行される 
        print("onSubscribe")
    }, onSubscribed: {
        // subscribe後に実行される 
        print("onSubscribed")
    })
    .subscribe({ (result) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Single<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.success("🐶"))
        observer(.success("🐱")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)

Maybe

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: MaybeEvent<String>) in
        switch result {
        case .success(let value):
            print("success: \(value)")
        case .completed:
            print("complete")
        case .error(let error):
            print("error: \(error)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Maybe<String>
    .create(subscribe: { (observer) -> Disposable in
        observer(.completed)
        observer(.success("🐶")) // ignored
        observer(.error(MyError.unknown)) // ignored
        return Disposables.create()
    })
    .subscribe(onSuccess: { (value) in
        print("success: \(value)")
    }, onError: { (error) in
        print("error: \(error)")
    }, onCompleted: {
        print("complete")
    })
    .disposed(by: disposeBag)

Completable

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe({ (result: CompletableEvent) in
        switch result {
        case .completed:
            print("complete")
        case .error(let value):
            print("error: \(value)")
        }
    })
    .disposed(by: disposeBag)

追記:3.4.0からは次のようにも書けます

let disposeBag = DisposeBag()

enum MyError: Error {
    case unknown
}

Completable
    .create(subscribe: { (observer) -> Disposable in
        observer(.error(MyError.unknown))
        observer(.completed) // ignored
        return Disposables.create()
    })
    .subscribe(onCompleted: { 
        print("complete")
    }, onError: { (error) in
        print("error: \(error)")
    })
    .disposed(by: disposeBag)

所感

今回追加されたUnitは使いたいシーンが結構ありそうです。
今まで Next が何回流れるか示したい場合はAppleDoc等で分かるようにしないといけませんでした。1回だけで良いのであれば、 SingleMaybe を使えば、ドキュメントに記載しなくても意図が明確になります。

95
67
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
95
67