RxSwift) Traits

Havi·2021년 4월 7일
0

RxSwift 기초

목록 보기
14/14

예제 코드 참고

Traits

코드를 직관적으로 작성해 사용할 수 있도록 도와주는 Observable 클래스의 모음

share 관련 토미님 글읽어보시는거 추천

Single

항상 단일 요소 또는 오류를 방출하도록 보장한다.
부수작용을 공유하지 않는다.
보통 응답 성공 / 실패 등을 다루는 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

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

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 {}
    }
}

RxCocoa Traits

Driver

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)
    }

Signal

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)
    }
profile
iOS Developer

0개의 댓글