코드를 직관적으로 작성해 사용할 수 있도록 도와주는 Observable 클래스의 모음
share 관련 토미님 글읽어보시는거 추천
항상 단일 요소 또는 오류를 방출하도록 보장한다.
부수작용을 공유하지 않는다.
보통 응답 성공 / 실패 등을 다루는 HTTP 요청에서 쓰이게 된다.
func fetchAPI(_ url: String) -> Single<[String:Any]> {
return Single<[String: Any]>.create { single in
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() }
}
}
Completable은 .complete나 .error만 방출하고, 아무런 element를 방출하지 않으며 부수작용을 공유한다.
func cacheLocally() -> Completable {
return Completable.create { completable in
// Store some data locally
...
...
guard success else {
completable(.error(CacheError.failedCaching))
return Disposables.create {}
}
completable(.completed)
return Disposables.create {}
}
}
Maybe는 .complete / .success / .error 중 하나를 방출한다.
부수작용을 공유하지 않는다.
func generateString() -> Maybe<String> {
return Maybe<String>.create { maybe in
maybe(.success("RxSwift"))
// OR
maybe(.completed)
// OR
maybe(.error(error))
return Disposables.create {}
}
}
self를 asDriver로 바꿔주면서 .empty()로 error를 recover 한다.
DriverSharingStrategy.scheduler에서 동작한다.
-> source.share(replay: 1, scope: .whileConnected)로 동작
-> 따라서 replay: 1에 따라 state 관리에 적합
extension ControlEvent {
/// Converts `ControlEvent` to `Driver` trait.
///
/// `ControlEvent` already can't fail, so no special case needs to be handled.
public func asDriver() -> Driver<Element> {
return self.asDriver { _ -> Driver<Element> in
#if DEBUG
rxFatalError("Somehow driver received error from a source that shouldn't fail.")
#else
return Driver.empty()
#endif
}
}
}
/**
Converts observable sequence to `Driver` trait.
- parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error.
- returns: Driver trait.
*/
public func asDriver(onErrorRecover: @escaping (_ error: Swift.Error) -> Driver<Element>) -> Driver<Element> {
let source = self
.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
.catchError { error in
onErrorRecover(error).asObservable()
}
return Driver(source)
}
self를 asSignal로 바꿔주면서 .empty()로 error를 recover 한다.
SignalSharingStrategy.scheduler에서 동작한다.
.share(scope: .whileConnected)한다 -> replay: 1을 하지 않음!
-> 따라서 replay해주지 않으므로 마지막 값을 전달하지 않음!
-> event 관리에 적합
extension ControlEvent {
/// Converts `ControlEvent` to `Signal` trait.
///
/// `ControlEvent` already can't fail, so no special case needs to be handled.
public func asSignal() -> Signal<Element> {
return self.asSignal { _ -> Signal<Element> in
#if DEBUG
rxFatalError("Somehow signal received error from a source that shouldn't fail.")
#else
return Signal.empty()
#endif
}
}
}
/**
Converts observable sequence to `Driver` trait.
- parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error.
- returns: Signal trait.
*/
public func asSignal(onErrorRecover: @escaping (_ error: Swift.Error) -> Signal<Element>) -> Signal<Element> {
let source = self
.asObservable()
.observeOn(SignalSharingStrategy.scheduler)
.catchError { error in
onErrorRecover(error).asObservable()
}
return Signal(source)
}