iOS SearchController 두번째, 검색바 데이터 filtering 처리 해보기
10 Apr 2022 | iOS개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
SearchController 두번째, 검색바 데이터 filtering 처리 해보기
사실 우리가 검색 컨트롤러를 사용하는 이유는 아래와 같죠.
- 내가 검색한 내용이 실제 검색이 되어야한다.
제일 중요한 부분입니다.
그러면 이제 그 제일 중요한 부분을 다뤄보도록 하겠습니다.
우선…
우선 기본적으로 제가 한 셋팅을 보여드리겠습니다.
class SearchViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var arr = ["zehye", "hi", "hello", "nice", "to", "meet", "you"]
override func viewDidLoad() {
super.viewDidLoad()
self.initUI()
self.setSearchControllerUI()
}
func initUI() {
self.tableView.delegate = self
self.tableView.dataSource = self
}
func setSearchControllerUI() {
let searchController = UISearchController(searchResultsController: nil)
// set placeholder
let placeholder = "검색창입니다"
searchController.searchBar.placeholder = placeholder
// searchController가 검색하는 동안 네비게이션에 가려지지 않도록
searchController.hidesNavigationBarDuringPresentation = false
// searchBar cancel button text change (cancel을 취소로 텍스트 변경)
searchController.searchBar.setValue("취소", forKey: "cancelButtonText")
// placeholder릐 글꼴과 글자 크기 변경
let attributedString = NSMutableAttributedString(string: placeholder, attributes: [
NSAttributedString.Key.font: UIFont(name: "Spoqa Han Sans Neo", size: 16) as Any,
NSAttributedString.Key.foregroundColor: UIColor(white: 255/255, alpha: 0.3)
])
searchController.searchBar.searchTextField.attributedPlaceholder = attributedString
// searchBar의 textField의 배경색, 폰트, 글자크기 변경
searchController.searchBar.searchTextField.backgroundColor = .clear
searchController.searchBar.searchTextField.font = UIFont(name: "Spoqa Han Sans Neo", size: 16)
// clear button 설정
if let button = searchController.searchBar.searchTextField.value(forKey: "_clearButton") as? UIButton {
let templateImage = button.imageView?.image?.withRenderingMode(.alwaysTemplate)
button.setImage(templateImage, for: .normal)
button.tintColor = .white
}
// 서치 컨트롤러 왼쪽에 back button color 변경
searchController.searchBar.searchTextField.leftView?.tintColor = UIColor.white
// searchBar cancel button color
searchController.searchBar.tintColor = UIColor.white
// navigation title
self.navigationItem.searchController = searchController
self.navigationItem.title = "검색하기"
// searchBar back button color
self.navigationItem.searchController?.searchBar.barTintColor = UIColor.white
// navigation item 스크롤 될때 사라지지 않게
self.navigationItem.hidesSearchBarWhenScrolling = false
// navigation item back button > back text remove (back 문구 없애기)
self.navigationController?.navigationBar.topItem?.backButtonDisplayMode = .minimal
// navigation item back button 이미지 변경
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "icBack")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "icBack")
}
}
extension SearchViewController: UITableViewDelegate, UITableViewDataSource {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arr.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SeachListCell") as! SearchListTableViewCell
cell.textLabel?.text = self.arr[indexPath.row]
return cell
}
}
- initUI()를 통해 테이블뷰 셋팅을 진행했고
- setSearchControllerUI()를 통해 서치 컨트롤러 셋팅을 진행했습니다.
- 나머지 tableview delegate, datasource 처리를 하였구요.
그럼 이제 중요한건 무엇일까요?
- 유저가 서치바에 무언가를 검색한다.
- 그러면 입력할때마다 해당되는 검색 내용이 아래 리로드 될 수 있도록 한다.
Filtering 진행
우선 서치바에 텍스트가 업데이트 될때 마다 불리는 메소드가 있어야 합니다.
searhController.searchResultsUpdater = self
위 코드를 setSearchControllerUI에 추가해 줍니다.
그리고 아래 코드도 같이 추가해 줍니다.
extension SearchController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
// code
}
}
위 코드는 우리가 서치바에 무언가를 검색할때마다 불려지는 함수입니다.
이 함수 안에서 우리가 서치바에 무언가 검색할때 무엇을 처리할지 적어주면 됩니다.
class SearchViewController: UIViewContoller {
...
var filterredArr: [String] = []
...
}
extension SearchController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
guard let text = searchController.searchBar.text?.lowercased() else { return }
self.filterredArr = self.arr.filter { $0.localizedCaseInsensitiveContains(text) }
dump(filterredArr)
}
}
이러면 로그에는 서치바가 업데이트 될때마다 반응을 하지만 실제 화면에서는 이루어지질 않죠?
그 이유는 아직 테이블 뷰에서 필터링된 데이터들에 대한 처리를 해주고 있지 않기 때문입니다.
class SearchViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
var arr = ["zehye", "hi", "hello", "nice", "to", "meet", "you"]
var filterredArr: [String] = []
var isFiltering: Bool {
let searchController = self.navigationItem.searchController
let isActive = searchController?.isActive ?? false
let isSearchBarHasText = searchController?.serarchBar.text?.isEmpty == false
return isActive && isSearchBarHasText
}
override func viewDidLoad() {
super.viewDidLoad()
self.initUI()
self.setSearchControllerUI()
}
func initUI() {
self.tableView.delegate = self
self.tableView.dataSource = self
}
func setSearchControllerUI() {
let searchController = UISearchController(searchResultsController: nil)
// set placeholder
let placeholder = "검색창입니다"
searchController.searchBar.placeholder = placeholder
// searchController가 검색하는 동안 네비게이션에 가려지지 않도록
searchController.hidesNavigationBarDuringPresentation = false
// searchBar cancel button text change (cancel을 취소로 텍스트 변경)
searchController.searchBar.setValue("취소", forKey: "cancelButtonText")
// placeholder릐 글꼴과 글자 크기 변경
let attributedString = NSMutableAttributedString(string: placeholder, attributes: [
NSAttributedString.Key.font: UIFont(name: "Spoqa Han Sans Neo", size: 16) as Any,
NSAttributedString.Key.foregroundColor: UIColor(white: 255/255, alpha: 0.3)
])
searchController.searchBar.searchTextField.attributedPlaceholder = attributedString
// searchBar의 textField의 배경색, 폰트, 글자크기 변경
searchController.searchBar.searchTextField.backgroundColor = .clear
searchController.searchBar.searchTextField.font = UIFont(name: "Spoqa Han Sans Neo", size: 16)
// clear button 설정
if let button = searchController.searchBar.searchTextField.value(forKey: "_clearButton") as? UIButton {
let templateImage = button.imageView?.image?.withRenderingMode(.alwaysTemplate)
button.setImage(templateImage, for: .normal)
button.tintColor = .white
}
// 서치 컨트롤러 왼쪽에 back button color 변경
searchController.searchBar.searchTextField.leftView?.tintColor = UIColor.white
// searchBar cancel button color
searchController.searchBar.tintColor = UIColor.white
// navigation title
self.navigationItem.searchController = searchController
self.navigationItem.title = "검색하기"
// searchBar back button color
self.navigationItem.searchController?.searchBar.barTintColor = UIColor.white
// navigation item 스크롤 될때 사라지지 않게
self.navigationItem.hidesSearchBarWhenScrolling = false
// navigation item back button > back text remove (back 문구 없애기)
self.navigationController?.navigationBar.topItem?.backButtonDisplayMode = .minimal
// navigation item back button 이미지 변경
self.navigationController?.navigationBar.backIndicatorImage = UIImage(named: "icBack")
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "icBack")
searhController.searchResultsUpdater = self
}
}
extension SearchViewController: UITableViewDelegate, UITableViewDataSource {
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.isFilterting ? self.filterredArr.count : self.arr.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SeachListCell") as! SearchListTableViewCell
if self.isFiltering {
cell.textLabel?.text = self.filterredArr[indexPath.row]
} else {
cell.textLabel?.text = self.arr[indexPath.row]
}
return cell
}
}
extension SearchController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
guard let text = searchController.searchBar.text?.lowercased() else { return }
self.filterredArr = self.arr.filter { $0.localizedCaseInsensitiveContains(text) }
self.tableView.reloadData()
}
}