-
[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)와만 묶이기 때문에, 다음과 같은 상황에서는 이전의 코드와 같아질 수 있다.error
와completed
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