RxSwift 3.3.0で3つのUnitが追加されました。
SingleMaybeCompletable
RxJavaにあったものが輸入された形のようです。
付属のPlaygroundに例が書かれていなかったので、ざっくりどんなものか確認してみました。
この記事は半分備忘録みたいなものになります。
追記
3.4.0で subscription closures (onSuccess, onError, onCompleted) が実装されました。
やっぱり欲しいよね。プルリク投げてくれたfreak4pcさんありがとう。
概要
まず前提として、 Observable は Completed あるいは Error が流れた時点でそれ以上何も流れなくなりますが、その2つが流れない限り Next は延々と流れてくる可能性があります。
それを踏まえて今回追加された3つのUnitについて見てみると、以下の表のようになります。
| Single | Maybe | Completable | |
|---|---|---|---|
| Success | ○ | ○ | × | 
| Completed | × | ○ | ○ | 
| Error | ○ | ○ | ○ | 
Success は 1回だけ流れる Next だと思って下さい。
そのSuccess が流れるのが Single と Maybe です。
Maybe は Success が流れず、 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回だけで良いのであれば、 Single や Maybe を使えば、ドキュメントに記載しなくても意図が明確になります。