RxSwift에서의 약한참조

subscribe나 bind를 할때 참조순환을 막기위하여 [weak self] 키워드를 쓰곤 했다.

viewModel.selectedIndex
  .subscribe(onNext: { [weak self] _ in 
	self?.tableView.reloadData()
  })
  .disposed(by: viewModel.disposeBag)

하지만 RxSwift에서 약한 참조를 선언하는 또 다른 방법이 있었다. RxSwiftExt(RxSwift 에 존재하지 않는 Operator 를 추가한 오픈 소스) 안에 있는 withUnretained라는 메소드인데 RxSwift 는 6 release 부터 withUnretained Operator 를 정식 채택 하였다고 한다.

withUnretained

viewModel.selectedIndex
  .withUnretained(self)
  .subscribe(onNext: { owner, _ in 
    owner.tableVIew.reloadData()
  })
  .disposed(by: viewModel.disposeBag)

이렇게 withUndetained에 매개변수로 self를 넘겨주면 클로저 안에서 원하는 키워드로 self를 약한참조할 수 있다!!
하지만 Error, Completed에 대한 핸들링을 할때는 다시 [weak self] 키워드가 필요하다.

Error / Completed

public enum Event<Element> {
    /// Next element is produced.
    case next(Element)
    /// Sequence terminated with an error.
    case error(Swift.Error)
    /// Sequence completed successfully.
    case completed
}

Next와 Error, Completed는 Event라는 열거형이다. 그 중 Next는 map,flatMap을 통해 우리가 원하는 요소의 유형으로 변경이 가능하지만 Error 와 Completed 는 RxSwift에서 정의해놓은 형식을 따르고있기 때문에 변경이 불가능 하다. 따라서 체인 아래에 있는 Reference 를 subscribe에게 전달할 방법이 없으므로 withUnretained 를 사용할 수가 없다.

subscribe(with:)

viewModel.selectedIndex
        .subscribe(with: self) { (owner, _) in
        	owner.tableVIew.reloadData()
        } onError: { (owner, error) in
			owner.tableVIew.reloadData()
        } onCompleted: { (owner) in
	   		owner.tableVIew.reloadData()
        }
        .disposed(by: viewModel.disposeBag)

이런식으로 subscribe(with:) 메소드를 사용하여 매개변수로 self를 넘겨주면 원하는 변수(owner)로 약한참조가 가능한 방법이 있다.

댓글남기기