UISearchController를 활용해서 검색 기능을 구현해보았습니다.
구현한 화면은 다음과 같습니다.
btc, 비트코인, bitcoin과 같은 검색어를 입력하면 필터링한 리스트를 새롭게 보여줍니다.
1. UISearchController를 생성해줍니다.
검색 중인지 상태를 알 수 있는 inSearchMode 변수도 만들어주었어요.
private let searchController = UISearchController(searchResultsController: nil)
private var inSearchMode: Bool {
return searchController.isActive && !searchController.searchBar.text!.isEmpty
}
2. 초기 설정을 해주어요.
func configureSerachController() {
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.hidesNavigationBarDuringPresentation = false
searchController.searchBar.placeholder = "코인명/심볼 검색"
navigationItem.searchController = searchController
definesPresentationContext = false
searchController.searchBar.setValue("취소", forKey: "cancelButtonText")
}
- `searchController.searchResultsUpdater = self` : UISearchController가 사용자가 입력한 검색어를 업데이트할 대상을 설정합니다. 여기서는 RootViewController가 업데이트 대상이 됩니다.
- `searchController.obscuresBackgroundDuringPresentation = false` : 검색바가 활성화될 때, 화면 배경이 검은색으로 가려지는 것을 방지합니다.
- `searchController.hidesNavigationBarDuringPresentation = false` : 검색바가 활성화될 때, Navigation Bar를 숨기지 않고 보여줍니다.
- `searchController.searchBar.placeholder = "코인명/심볼 검색"` : 검색바에 미리 보여질 placeholder text를 설정합니다.
- `navigationItem.searchController = searchController` : 현재 UIViewController의 navigationItem의 searchController를 설정합니다.
- `definesPresentationContext = false` : 다른 ViewController로 이동하면 searchController를 해제합니다.
- `searchController.searchBar.setValue("취소", forKey: "cancelButtonText")` : 검색바 내에 있는 "cancel" 버튼의 텍스트를 "cancel" 대신 다른 텍스트로 바꿀 수 있습니다. 이 경우 "cancel" 버튼의 텍스트를 "cancel"에서 "취소"로 바꿉니다.
3. UICollectionView의 numberOfItemsInSection, cellForItemAt을 필터링 된 리스트를 보여줄 수 있도록 수정해주어요.
삼항 연산자를 활용해서 inSearchMode에 따라서 값을 변경해주어요.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return inSearchMode ? vm.filterdCoins.count : vm.volume.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! TickerCell
let coin = inSearchMode ? vm.filterdCoins[indexPath.row] : vm.volume[indexPath.row]
cell.configure(with: coin)
return cell
}
4. UISearchResultsUpdating의 updateSearchResults 함수로 텍스트 필드의 값이 없데이트되면 필터링 코드를 실행해요.
extension RootViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
guard let searchText = searchController.searchBar.text?.lowercased() else { return }
let coins = vm.volume.filter({
$0.symbol.lowercased().contains(searchText) ||
$0.koreanName.contains(searchText) ||
$0.englishName.lowercased().contains(searchText)
})
vm.filterdRelay.accept(coins)
self.collectionView.reloadData()
}
}
여기까지 하셨으면 완성입니다!
다만.. 검색하다가 다른 화면을 누르면 키보드가 내려가게 하거나, 편집 상태를 종료하고 원래 상태로 돌아가고 싶을 때 다음과 같은 코드를을 추가 할 수 있어요.
UICollectionView의 다른 화면을 드래그하기 시작하면 키보드 내리기
private lazy var collectionView: UICollectionView = {
let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
cv.delegate = self
cv.dataSource = self
cv.backgroundColor = .white
cv.register(TickerCell.self, forCellWithReuseIdentifier: reuseIdentifier)
cv.register(RootHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerIdentifier)
cv.keyboardDismissMode = .onDrag // UICollectionView를 스크롤하기 시작하면 키보드가 내려갑니다.
return cv
}()
UICollectionViewDelegate에 메서드를 이용하여 UISearchController의 편집상태를 종료할 수도 있어요.
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
guard !inSearchMode else { return }
searchController.dismiss(animated: false)
}
이렇게 하면 꽤나 멋있는 검색바와 필터링 기능을 구현할 수 있습니다!
실제 서비스에서는 검색결과가 없을 때 스켈레톤 플레이스 홀더 등을 보여주거나 하면 더 완성도가 높아질 것 같아요.
이번에 UIKit을 공부하면서 UISearchController를 활용한 검색기능을 구현해봤는데,
포커싱되면 취소버튼이 나오거나, 텍스트 필드 삭제버튼이 나타나거나 하는 기능이 모두 준비되어 있어서 놀라웠어요.
SwiftUI로 작업할 때는 한땀한땀 구현하느라 애먹었던 기억이 있어요.
UIKit의 작점을 발견하게 되었으니 앞으로도 즐겁게 공부해보겠습니다!
홧팅!
'Project > UIKit 업비트' 카테고리의 다른 글
[UIKit] TableView에서 insetGrouped 스타일로 섹션을 나눠보자 (0) | 2023.04.22 |
---|---|
[UIKit] TableView 위에 Header를 만들어보자 (0) | 2023.04.22 |
[UIKit] 업비트 API로 CollectionView에 리스트 만들기 feat.RxCocoa (0) | 2023.04.13 |
[UIKit] CollectionView가 먼저 생성되고 데이터가 갱신되지 않는 문제 (0) | 2023.04.07 |
[UIKit] 탭 바 배경색이 투명할 때 해결방법 (0) | 2022.12.17 |
댓글