[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Combine & Rx

[RxSwift] Trait (Single, Completable, Maybe)

inu 2022. 2. 24. 15:14
반응형

이번엔 RxSwift의 Trait들에 대해 알아보았습니다.


Trait

Trait은 Observable을 좀 더 안정성있고 의미있게 표현하기 위한 일종의 Syntax Sugar입니다. 그 종류로는 Single, Completable, Maybe가 있습니다. Observable을 좀 더 좁은 범위로 제한하여 제공함으로써 코드를 더 명시적으로 표현하는 것이죠.

 

일반적으로 Trait은 아래와 같이 단순히 read-only Observable의 wrapper 형태로 구성되어 있습니다. 이렇게 Observable에 대한 접근을 제한해놓고 내부에 존재하는 Observable를 조정하여 일부 기능에 특화된 형태로 사용자에게 제공합니다.

struct Single<Element> {
    let source: Observable<Element>
    ...
}

Single

  • .success(value) 혹은 .error 이벤트만을 방출합니다. .success(value)는 .next와 .completed가 합쳐져 있는 형태라고 생각하시면 됩니다. 성공 또는 실패로 한번에 확인할 수 있는 1회성 프로세스에 적절합니다. (ex. 데이터 다운로드, 디스크 데이터로딩)
  • asSingle() 메서드를 통해 아무 Observable을 Single로 변환시켜서 확인할 수 있습니다.
  • 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
func getRepo(_ repo: String) -> Single<[String: Any]> {
    return Single<[String: Any]>.create { single in
        let task = URLSession.shared.dataTask(with: URL(string: "https://api.github.com/repos/\(repo)")!) { 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() }
    }
}
  • subscribe로 이를 활용할 수 있습니다.
  • SingleEvent는 .success 혹은 .error만을 제공합니다.
getRepo("ReactiveX/RxSwift")
    .subscribe { event in
        switch event {
            case .success(let json):
                print("JSON: ", json)
            case .error(let error):
                print("Error: ", error)
        }
    }
    .disposed(by: disposeBag)

 

Completable

  • .completed 혹은 .error만을 방출하며 그 외에 어떠한 값도 방출하지 않습니다. 특정 처리가 제대로 완료되었는지만 확인하고 싶을 때 많이 사용합니다. (ex. 파일 쓰기)
  • observable이 값요소를 방출한 이상, 이를 Completable로 변환시킬 수는 없습니다.
  • 이 역시 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
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 {}
    }
}
  • subscribe로 이를 활용할 수 있습니다.
  • CompletableEvent는 .completed 혹은 .error만을 제공합니다.
cacheLocally()
    .subscribe { completable in
        switch completable {
            case .completed:
                print("Completed with no error")
            case .error(let error):
                print("Completed with an error: \(error.localizedDescription)")
        }
    }
    .disposed(by: disposeBag)

 

Maybe

  • Single과 Completable이 섞인 버전입니다. .success(value), .completed, .error 모두 방출될 수 있습니다. 프로세스가 성공 실패여부와 더불어 특정 값을 뱉을 수 있을 때 사용합니다.
  • asMaybe() 메서드를 통해 아무 Observable을 Maybe로 변환시켜서 확인할 수 있습니다.
  • 이 또한 생성과 사용은 Observable과 유사합니다. 아래 예제를 봅시다.
func generateString() -> Maybe<String> {
    return Maybe<String>.create { maybe in
        maybe(.success("RxSwift"))

        // OR

        maybe(.completed)

        // OR

        maybe(.error(error))

        return Disposables.create {}
    }
}
  • subscribe로 이를 활용할 수 있습니다.
generateString()
    .subscribe { maybe in
        switch maybe {
            case .success(let element):
                print("Completed with element \(element)")
            case .completed:
                print("Completed with no element")
            case .error(let error):
                print("Completed with an error \(error.localizedDescription)")
        }
    }
    .disposed(by: disposeBag)

참고

반응형

'🍎 Apple > Combine & Rx' 카테고리의 다른 글

[RxSwift] Driver, Signal  (0) 2022.02.24
[RxSwift] ControlProperty, ControlEvent  (0) 2022.02.24
[RxSwift] Scheduler  (2) 2022.02.24
[RxSwift] Subject  (0) 2022.02.16
[RxSwift] Observable & Operator  (0) 2022.02.14