[UIKit] NetflixClone: SearchViewController 2

Junyoung Park·2022년 11월 1일
0

UIKit

목록 보기
73/142
post-thumbnail

[https://www.youtube.com/watch?v=HnWWo0b4v9w&list=PLqj8V2bxPxpDRRpKl01DS5qc3ImXb_MYg&index=10](NetflixClone: SearchViewController 1)

NetflixClone: SearchViewController 2

구현 목표

  • 검색 결과 뷰 컨트롤러 구현
  • 텍스트 필드 입력 시간에 따른 쿼리 수행 조절

구현 태스크

  • 커스텀 검색 결과 뷰 컨트롤러 및 뷰 모델 구현
  • 커스텀 텍스트 필드 퍼블리셔를 통한 쿼리 작성 시간 조정
  • 자동 데이터 패치 및 UI 표시

핵심 코드

private let searchController: UISearchController = {
        let results = SearchResultViewController()
        let vc = UISearchController(searchResultsController: results)
        vc.searchBar.placeholder = "검색"
        vc.searchBar.searchBarStyle = .minimal
        vc.definesPresentationContext = true
        return vc
    }()
  • 서치 바를 구현할 때 파라미터로 커스텀 뷰 컨트롤러를 통해 이니셜라이즈함
  • 이후 타입 캐스팅을 통해 커스텀한 뷰 컨트롤러 내의 퍼블릭 함수를 현재 present하고 있는 뷰 컨트롤러 단에서 사용 가능
let publisher = NotificationCenter.default.publisher(for: UISearchTextField.textDidChangeNotification, object: searchController.searchBar.searchTextField)
        publisher
            .compactMap({$0.object as? UISearchTextField})
            .map({ $0.text })
            .debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
            .sink { [weak self] queryString in
                guard
                    let queryString = queryString,
                    !queryString.trimmingCharacters(in: .whitespaces).isEmpty,
                    let resultVC = self?.searchController.searchResultsController as? SearchResultViewController else { return }
                resultVC.getSearchedResult(with: queryString)
                
            }
            .store(in: &cancellables)
  • 텍스트 필드 입력이 500 밀리초 이상 중단된다면 곧바로 쿼리문을 체크, resultVCgetSearchedResult 함수를 실행하는 바인딩 구문
func getSearchedResult(with query: String) {
        viewModel
            .getSearchResultContents(with: query)
    }
  • 쿼리문은 다음과 같은 뷰 모델 내 함수를 실행
func getSearchResultContents(with query: String) {
        APICaller
            .shared
            .getSearchResultContents(with: query)
            .sink { completion in
                switch completion {
                case .failure(let error): print(error.localizedDescription)
                case .finished: break
                }
            } receiveValue: { [weak self] resultModels in
                print(resultModels)
                self?.searchResultsModel.send(resultModels)
            }
            .store(in: &cancellables)
    }
  • 검색 바의 텍스트 필드 중지 이벤트를 통해 호출한 해당 API 함수 호출을 통해 실제 비동기 데이터를 패치
  • 데이터 퍼블리셔가 새로운 값으로 변경될 때 뷰 컨트롤러에서 바인딩한 조건에 따라 컬렉션 뷰가 실행, 데이터 패치로 받아온 값을 컬렉션 뷰 그리드를 통해 그리기

구현 화면

profile
JUST DO IT

0개의 댓글