티스토리 뷰

키보드의 검색 버튼을 입력했을때 뿐만아니라 키워드를 입력할때마다 Request를 요청할수 없을까?? (rx.text로 변경된 text감지하기)

4줄 요약

  1. RxCocoa의 text (SearchBar.rx.text)를 이용해 text변경시 Request를 요청하도록 구현함.
  2. 의도한것과 다르게 처음 키워드를 입력할때와 키보드 제거시 Request요청 하는 문제가 발생함.
  3. text Definition을 확인해보니 SearchBar의 text가 nil일경우 "" 으로 옵셔널바인딩 하는것과 키보드제거(편집 종료) 되었을때도 text를 방출하는것을 확인함.
  4. distinctUntilChanged()오퍼레이터를 사용해 동일한 text를 방출하게될경우 무시하도록 하여 문제를 해결함.

처음 API Search기능 구현시 키보드의 검색 버튼을 tap할경우 Request를 요청하도록 했다.

self.searchBar.searchTextField.rx.controlEvent(.editingDidEndOnExit)
    .bind { [weak self] _ in
        //API Request 요청 메서드
        self?.viewModel.fetchFirstPage(text: self?.searchBar.text)
        self?.endEditing(true)
    }
    .disposed(by: disposeBag)

RxSwift를 사용해 구현하였으며 .editingDidEndOnExit TextField의 검색 버튼을 tap했을때 발생하는 이벤트를 구독하고있다가 이벤트가 전달되면 API Request를 요청했다.

그리고 .endEditing을 사용하여 현재 활성화된 SearchBar를 비활성화 하도록했다.(SearchBar를 사용해 검색중이었으면 당연히 SearchBar가 활성화 되어있을테니 .endEditing을 사용하면 FirstResponder인 SearchBar가 비활성화 되고 키보드가 제거된다!)

해당 기능을 구현후 쿠팡앱을 이용해 냉동식품을 검색하던중 키워드를 입력할때마다 입력한 키워드가 포함된 예상 검색어 목록 을 보여주는 tableView 를 보게 되었고 Book Finder앱에서도 키워드를 검색할때마다 Request를 요청해 입력한 키워드와 일치하는 정보를 가진 책정보들을 보여주도록 하는것으로 변경하였다.

self.searchBar.rx.text.orEmpty
    .bind { [weak self] text in
        //API Request 요청 메서드
        self?.viewModel.fetchFirstPage(text: text)
    }
    .disposed(by: self.disposeBag)

위의 코드를 살펴보자!
RxCocoa의 text를 사용하게되면 SearchBar에 입력된 text가 변경 될때마다 text에 입력된 String 값을 전달해주는데 이때 옵셔널값으로 전달해준다.
입력을했는데!? 왜 옵셔널값으로 받아야하지!? text가 변경될경우 무조건 값이 있어야 하는데!?

.orEmpty를 사용해서 옵셔널을 걸러주었다!
그후 전달된 text로 API Request를 요청해주었는데 문제가 발생했다.

키워드를 입력하기전에 String = "" 값으로 Request를 요청하게 되고, 키보드가 제거 되었을때 마지막으로 입력한 값을 한번더 Request 요청하게 된다.

RxCocoa의 text는 SearchBar의 text 값을 변경할때 변경된 값을 전달해주는 녀석으로 알고있었는데 text가 변경되지 않았을때도 이벤트를 전달해주는것으로 추측했다.

text의 Definition을 확인해보니 value를 reutrn 한다.

그렇담 value는 무엇이냐!?

source의 return값을 보면 textDidChange와 didEndEditing를 묶어서 전달하고 text값이 옵셔널일 경우 String = "" 을 전달하는것을 볼수있다!
(SearchBar에 처음 키워드를 입력시 값이 아무것도없는 nil이기 때문에 이를 "" 으로 변경해서 전달해주는것을 알수있다!)

didEndEditing을 보면 UIKit의 searchBarTextDidEndEditing을 호출하는데 이는 SearchBar의 text편집 종료시 편집이 종료되었다고 알려주는 메서드다!

추측한대로 편집이 종료될때(비활성화 되어 키보드가 제거 될때) 마지막으로 입력된 text를 방출하게 되는것이다!

그렇다면 문제를 해결하기위해서는 처음 ""값을 방출하지 않도록 하고, 편집이 종료되었을때 마지막으로 변경했던 text값을 한번더 방출하지 않도록 해주어야 한다!

이전 프로젝트에서 사용해본 distinctUntilChanged()가 생각났다.
distinctUntilChanged() 요녀석은 이전의 이벤트값과, 발생한 이벤트값이 같을경우 전달하지 않도록 하는 오퍼레이터다!

이녀석을 사용하기 위해서는 이전이벤트값과 새로 발생한 이벤트값이 같은지 확인해주어야 하기 때문에 Equatable을 채택한 타입만 사용할수 있지만 String은 Equatable을 채택하고 있기때문에 사용할수있다!

self.searchBar.rx.text
    .orEmpty
    .distinctUntilChanged()
    .bind { [weak self] text in
        self?.viewModel.fetchFirstPage(text: text)
    }
    .disposed(by: self.disposeBag)

요렇게 distinctUntilChanged() 적용했더니 문제가 해결되었다.
처음 "" 값은 SearchBar에 아무것도 입력하지 않았을때는 nil이고 이는곧 ""으로 변경된다.

그후 SearchBar를 활성화 시키게되면 text를 입력하지 않았기 때문에 ""(nil)이 방출되는데 distinctUntilChanged()를 사용해 이전값과 같으면 무시하도록 했기 때문에 ""값이 방출되지 않는다.

그리고 키보드를 제거했을때(편집을 종료했을때)도 마찬가지로 마지막으로 입력한 키워드와 동일한값을 방출하기때문에 무시되므로 원하는 결과를 얻을수 있었다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함