버그 잡이

RxSwift - subscribe시 onNext를 명시해줘야 하는 이유 본문

RxSwift

RxSwift - subscribe시 onNext를 명시해줘야 하는 이유

버그잡이 2020. 10. 26. 19:42

RxSwift 에서 .subscribe()를 사용하면 Observable을 구독할 수 있습니다.

 

아래 코드는 emailView 터치를 구독하는 코드를 예시로 살펴보겠습니다.

 

emailView.rx.tapGesture().when(.recognized).subscribe(
onNext: { [unowned self] _ in
    self.sendEmail()
}, 
onError: { error in

}, 
onCompleted: {

}) {

}

 

정석적인 방법은 위처럼

subscribe() 안에 onNext, onError, onCompleted, onDisposed 에 따라 알맞은 코드를 각각 작성합니다.

 

그런데 아래와 같이 간단하게 작성할 수도 있습니다.

 

emailView.rx.tapGesture().when(.recognized).subscribe({ [unowned self] _ in
        self.sendEmail()
    }).disposed(by: disposeBag)

 

 

subscribe() 안에 세부 사항을 구분하지 않고 subscribe로 퉁치는 것이죠.

위와 같이 작성하면 코드량도 줄어들고 보기에도 더 깔끔합니다.

 

 

“하지만 위 코드는 치명적인 문제점이 있습니다.”

 

 

onNext, onCompleted, onError를 구분해서 받지 않기 때문에

subscribe() 내부 로직이 onNext 일때만(터치가 정상 인식 되었을때) 동작하는 것이 아니라

onCompleted 일때도 self.sendEmail() 메서드를 실행시킵니다.

onCompleted는 해당 구독이 중지될때 실행됩니다. 보통은 메모리에서 해제될때 onCompleted가 발행되죠.

이때 실행시키고자 하는 구문에 [unowned self]와 같은 참조가 걸려있다면, 크래쉬가 날 수 있습니다.

 

인스턴스 해제 → emailView.rx.tapGesture() 구독 해제

→ onCompleted 발행 → self.sendEmail() 호출 → 존재하지않는 self로 인한 crash

 

 

 

“두가지 교훈”

 

여기서 두 가지 교훈을 얻을 수 있습니다.

 

1) .subscribe()를 쓸때는 onNext를 구분해주자.

 

2) [unowned self] 쓰지 말고 [weak self] 를 쓰자

 

 

반응형
Comments