RxSwift 3.3.0で3つのUnitが追加されました。
Single
Maybe
Completable
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
を使えば、ドキュメントに記載しなくても意図が明確になります。