Search

검색 및 필터링 기능 구현하기

기본 설정 및 UISearchController 구성

private let searchController = UISearchController(searchResultsController: nil) func configureSearchController() { searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false searchController.hidesNavigationBarDuringPresentation = false searchController.searchBar.autocapitalizationType = .none searchController.searchBar.autocorrectionType = .no searchController.searchBar.spellCheckingType = .no searchController.searchBar.placeholder = "Search" navigationItem.searchController = searchController definesPresentationContext = false }
Swift
복사
searchResultsUpdater 프로퍼티를 현재 클래스(self)로 설정하여 사용자가 검색 바에 입력할 때마다 결과 업데이트
검색 중에 배경을 흐리게 하지 않음
내비게이션 바를 숨기지 않음
자동 대문자 비활성화
자동 수정 비활성화
맞춤법 검사 비활성화

검색 모드

private var inSearchMode: Bool { return searchController.isActive && !searchController.searchBar.text!.isEmpty }
Swift
복사
이 계산 속성은 사용자가 검색 중인지 아닌지를 파악하여 해당 상태에 따라 테이블 뷰에 표시될 데이터를 결정한다.
inSearchMode가 true일 때 사용자는 검색을 활성화하고 검색어를 한 글자 이상 입력한 상태이다. 이 경우, SearchController는 filteredUsers 배열을 사용하여 테이블 뷰를 채운다. 이 배열에는 사용자의 검색 조건에 부합하는 사용자 데이터만 포함되어 있다.

사용 이유

이 속성을 사용하는 이유는 사용자가 어떻게 데이터를 보고 싶어하는지, 즉 전체 목록을 보고 싶은지 아니면 특정 조건을 만족하는 항목만 보고 싶은지를 파악하기 위함이다. 이를 통해 앱은 사용자 경험을 개선하고 필요한 정보만을 효율적으로 제공할 수 있다.

isSearchMode를 활용한 동적 테이블 뷰 데이터 처리

extension SearchController { override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return inSearchMode ? filteredUsers.count : users.count } override func tableView( _ tableView: UITableView, cellForRowAt indexPath: IndexPath ) -> UITableViewCell { let cell = tableView.dequeueReusableCell( withIdentifier: reuseIdentifier, for: indexPath ) as! UserCell let user = inSearchMode ? filteredUsers[indexPath.row] : users[indexPath.row] cell.viewModel = UserCellViewModel(user: user) return cell } }
Swift
복사
isSearchMode의 값에 따라 행의 수를 결정한다. 검색 모드가 활성화되면 filteredUsers 배얄의 크기를 반환하고 그렇지 않으면 users 배열의 크기를 반환한다.

테이블 뷰 델리게이트 메서드 활용

extension SearchController { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let user = inSearchMode ? filteredUsers[indexPath.row] : users[indexPath.row] let controller = ProfileController(user: user) navigationController?.pushViewController(controller, animated: true) } }
Swift
복사
사용자가 테이블 뷰의 셀을 선택하면 isSearchMode 상태에 따라 적절한 사용자 데이터를 가져온다. 이 데이터는 선택된 사용자의 프로필을 보여주는 ProfileController로 전달된다.

검색 로직 및 필터링

func updateSearchResults(for searchController: UISearchController) { guard let searchText = searchController.searchBar.text?.lowercased() else { return } filteredUsers = users.filter({ $0.username.lowercased().contains(searchText) || $0.fullname.lowercased().contains(searchText) }) tableView.reloadData() }
Swift
복사
검색어가 입력될 때마다 updateSearchResults(for:) 메서드가 호출된다. 입력된 텍스트를 소문자로 변환한 후, username 또는 fullname에 검색어가 포함되는지 확인한다.
소문자로 변환하는 이유는 일관성을 유지하기 위함인데 사용자가 입력하는 텍스트는 대소문자를 혼용할 수 있기 때문이다. 예를 들어, 사용자가 ‘apple’, ‘Apple’, ‘APPLE’로 검색할 수 있다. 모든 입력을 소문자로 변환함으로써 데이터 소스의 해당 필드도 소문자로 변환하여 비교하여 일관된 검색 결과를 제공한다. 즉, 검색 정확도를 향상시킨다.
필터링된 사용자를 filteredUsers 배열에 저장하고 테이블 뷰에 변경사항을 반영한다.