티스토리 뷰

반응형

textfield.rx.text가 당연히 textfield의 text가 변할 때만 이벤트가 방출되는 줄 알았는데, 아니라는 것을 알게 되어서 정리합니다..!

UILabel은 빼고 사용자 입력에 따라 텍스트가 변하는 UI 삼인방(?)  UITextField, UISearchBar, UITextView 를 살펴봅니다 

 

이렇게 실험을 준비해줍니다 

 

1. textField.rx.text

 

UITextField+Rx.swift 파일에 들어가줍니다 

 

controlPropertyWithDefaultsEvents에 들어가봅니다

😱😱 놀랍게도 valueChanged뿐만 아니라 allEditingEvents에도 트리거 된다는 것을 확인할 수 있습니다...!!! 😱😱 



 allEditingEvents는 텍스트 필드에 editing 하려는 모든 터치를 의미합니다 

 

그래서 text가 변할 때 뿐만 아니라
커서가 포커스 -> 언포커스 또는 언포커스 -> 포커스 로 변할 때도 값을 방출합니다 

위에서 봤듯이 'editing 하려는 모든 터치'일 때 값을 방출하게 만들어놨기 때문입니다..!!

 

 

하지만 'editing 하려는 모든 터치' 라는 표현은 좀 위험의 소지를 가지는데,
becomeFirstResponser를 연속으로 눌러서 포커스 -> 포커스 -> 포커스... 되는 상황이나

resignFirstResponser와 viewEndEditing을 연속으로 눌러서  언포커스 -> 언포커스  -> 언포커스... 되는 상황 에는 

값이 방출되지 않기 때문입니다. 포커스 상태가 바뀔 때만 값이 방출됩니다....! 

 

 

2. searchBar.rx.text

 

UISearchBar+Rx.swift에 들어가줍니다 

 

text가 바뀌었을 때, text editing이 끝났을 때 트리거 해주네요 

 

 

그래서 text가 바뀌었을 때와 text editing이 끝났을 때(언포커스 상태로 변할 때) 값이 방출됩니다
(resignFirstReponder를 연속으로 눌러서 언포커스 -> 언포커스 -> 언포커스.. 해도 값이 방출되지 않습니다. 포커스에서 언포커스 상태로 변할 때만 방출!!!)

textfield.rx 와는 다르게 포커스 상태로 변할 때는 값이 방출되지 않습니다 

 

 

3. textView.rx.text 

 

마지막으로 UITextView+Rx.swift 에 들어가봅시다 

 

 

didProcessEditingRangeChangeInLength에 들어가보면


이런 delegate안의 함수로 무엇을 해주는데, 이 함수가 정확히 어떤 건지는 잘모르겠습니다ㅠㅠ (나중에 알아보기!!) 

아무튼 searchbar와 마찬가지로 

text가 바뀌었을 때, text editing이 끝났을 때 트리거 해줍니다

 

 

테스트해보면, text가 바뀌었을 때와 text editing이 끝났을 때(언포커스 상태로 변할 때) 값이 방출됩니다

(resignFirstReponder를 연속으로 눌러서 언포커스 -> 언포커스 -> 언포커스.. 해도 값이 방출되지 않습니다. 포커스에서 언포커스 상태로 변할 때만 방출!!!)

포커스 상태로 변할 때는 값이 방출되지 않습니다 

 

 

 

마무리 

1) rx.text는 text가 변할 때만 이벤트가 방출되지 않는 다는 점, 
2) textfield.rx.text는 searchbar.rx.text & textview.rx.text와는 조금 다르다는 점
유의하고 rx.text를 써야할 것 같습니다....!!!! 

 

 

예를 들어 searchBar.rx.text가 방출하는 텍스트를 보고 있다가, 그 텍스트를 가지고 search API를 콜 해주게 만들었다고 합시다 

근데 사용자가 '백예린' 까지 입력하고 키보드 밖의 view를 눌러서 키보드가 hide 되었다고 합시다

그러면 키보드가 hide되면서 searchBar가 언포커스되고 searchBar.rx.text이 '백예린' 이라는 값을 방출합니다. 

그러면 '백예린' 이라는 text로 API Call이 두번 일어나게 되는 것입니다...🥶

 

이런 현상을 방지하기 위해서 제가 쓰는 방법은 distinctUntilChanged 연산자 입니다. 

searchbar를 예로 들어보겠습니다. searchbar.rx.text.distinctUntilChanged() 이런식으로 
searchbar.rx.text 뒤에 distinctUntilChanged 연산자를 붙여서 다른 값만 방출해주는 스트림으로 바꿔서 쓰는 방법입니다 

 

 

저는 실제로 textfield.rx.text가 당연히 text가 변할때만 방출되는 줄 알고 쓰다가 이렇게 작동하는 것을 발견하게 되서 충격을 받았는데요...ㅠㅠㅠㅠㅠ 

 

앞으로 주의해야겠습니다... 🙈

 

반응형
댓글