ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [RxSwift6] "withUnretained" operator로 리펙토링하기
    iOS/RxSwift 2022. 2. 2. 22:17

    이전에 글로 남겼다시피 subscribe, bind, drive등을 통해서 구독할 때 순환참조의 문제점을 방지하기 위해서 weak self를 통해서 약한참조를 만들어주었다.

    observable
            .subscribe(onNext: { [weak self] (string) in
                guard let self = self else { return }
                self.doSomething(string)
            })
            .disposed(by: disposeBag)

    이 방식은 확실한 방법이였지만, 보일러 플레이트가 계속해서 만들어져 코드를 지저분하게 만들었다.

    RxSwiftCommunity의 RxSwiftExt에 있던 withUnretained operator은 이런 코드를 조금 더 명료하게 만들어주어 인기가 많았고, RxSwift 6.0에 공식적으로 추가되었다.

    사용법은 매우 간단한데 아래 코드만 보고도 따라할 수 있다.

    observable
            .withUnretained(self)
            .subscribe { (owner, string) in
                owner.doSomething(string)
            }
            .disposed(by: disposeBag)

    한계점

    withUnretained은 observable의 value(element)와만 묶이기 때문에, 다음과 같은 상황에서는 이전의 코드와 같아질 수 있다.

    errorcompleted evnet는 value(element)와는 별개이기 때문이다.

    observable
            .withUnretained(self)
            .subscribe { (owner, string) in
                owner.doSomething(string)
            } onError: { [weak self] (error) in
                guard let self = self else { return }
                self.handleError(error)
            } onCompleted: { [weak self] () in
                guard let self = self else { return }
                owner.handleDone()
            }
            .disposed(by: disposeBag)

    또한 chaining을 위해서는 매 chain마다 withUnretained구문을 작성해주어야 한다.

    func setupLogin(_ submit: Observable<(String?, String?)>) -> Observable<User> {
        return submit
            .withLatestFrom(credentials)
            .withUnretained(self)
            .flatMap { (model, creds) -> Observable<String> in
                model.authorize(username: creds.0, password: creds.1)
            }
            .withUnretained(self)
            .flatMap { (model, token) -> Observable<User> in
                model.user(authorization: token)
            }
    }

    그렇기 때문에 단 한번 사용해야 할 때에는 매우 추천하지만, 위처럼 어쳐피 길어질 코드에서는 이전처럼 작성하는것과 별반 다르지 않을 것 같은 느낌이 든다.

    하지만 또, 가독성 측면에서는 조금 더 좋을 것 같기 때문에 withUnretined를 계속 써줄 생각이다.

    'iOS > RxSwift' 카테고리의 다른 글

    [RxSwift] weak, unowned self에 대한 의문  (0) 2022.01.27
    [RxSwift] Error Handling [2]  (0) 2022.01.27
    [RxSwift] Error Handling [1]  (0) 2022.01.25
    RxSwift로 리펙토링 맛보기  (0) 2022.01.03
    [Rxswift] 03.Subjects  (0) 2021.12.19

    댓글

Designed by Tistory.