
일단 내 뷰를 크게 top, body로 나누었다. top에는 서치바 있는 부분 SearchView가 들어가고, body에는 최신검색어가 나오는 부분인 LastSearchedView와 검색결과가 나오는 부분인 ResultView가 들어간다.

검색창을 보면 서치바를 사용하는 것 뿐만 아니라 커스텀까지 해야했다!!🙊🙉
서치바를 사용하는 방법은 tableView와 비슷한다. UISearchBarDelegate를 지정해줘야한다.
일단 먼저 서치바를 만들어주고 커스텀을 해준다.
lazy var searchBar: UISearchBar = {
let search = UISearchBar()
search.placeholder = "영화를 검색해보세요"
search.searchBarStyle = .minimal
search.searchTextField.borderStyle = .none
search.delegate = self
if let tf = search.value(forKey: "searchField") as? UITextField {
if let leftView = tf.leftView as? UIImageView {
leftView.tintColor = .megaRed
}
}
return search
}()
lazy var로 정의 : 초기화 시점을 지연시켜 메모리를 효율적으로 사용할 수 있다!! 이에 대해서는 나중에 꼼꼼히 정리해봐야겠음.
여기서 searchBar는 여러 키값을 가지고 있는데 searchField는 검색 바의 텍스트 필드에 직접 접근할 수 있게 해준다. 이를 value(forKey:)로 받아온 다음 UITextField로 다운캐스팅 해주었다.

여기서 텍스트필드에는 검색창 뿐만 아니라 옆에 검색 버튼도 있는데 이 버튼도 UIImageView로 다운캐스팅 해와서 색을 바꾸어 주었다!!

일단 요렇게 나온다.
다운캐스팅 한번 더 정리!
- 안전한 다운캐스팅(as?): 다운캐스팅이 실패할 수 있는 경우에 사용. 다운캐스팅이 실패하면 nil을 반환.
- 강제 다운캐스팅(as!): 다운캐스팅이 확실히 성공할 것으로 확신할 때 사용. 만약 다운캐스팅이 실패하면 런타임 에러가 발생.
여기서 나는 서치바 자체를 커스터마이징 하지 않고 뒤에 뷰를 하나 만들어주고 서치바를 투명하게 만들어주어서 마치 서치뷰가 동그란 것 처럼 했다!! 이 뷰에 그림자 효과도 주었다!!
let searchView: UIView = {
let bgview = UIView()
bgview.layer.shadowColor = UIColor.black.cgColor
bgview.layer.shadowOpacity = 0.6
bgview.layer.shadowOffset = CGSize(width: 0, height: 0)
bgview.layer.shadowRadius = 5
bgview.layer.masksToBounds = false
bgview.layer.shouldRasterize = false
bgview.backgroundColor = UIColor.white
bgview.layer.borderWidth = 1
bgview.layer.borderColor = UIColor.clear.cgColor
bgview.layer.cornerRadius = 20
return bgview
}()
그런데 지금 정리하면서 서치바 자체를 커스텀 하는 것도 가능한 것을 발견! 왜 그때는 해볼 생각을 안했지? 🫤
lazy var searchBar: UISearchBar = {
let search = UISearchBar()
search.placeholder = "영화를 검색해보세요"
search.layer.cornerRadius = 20
search.layer.borderColor = UIColor.black.cgColor
search.layer.borderWidth = 1
search.searchBarStyle = .minimal
search.searchTextField.borderStyle = .none
search.layer.shadowColor = UIColor.black.cgColor
search.layer.shadowOpacity = 0.6
search.layer.shadowOffset = CGSize(width: 0, height: 0)
search.layer.shadowRadius = 8
search.layer.masksToBounds = false
search.layer.shouldRasterize = false
search.delegate = self
if let tf = search.value(forKey: "searchField") as? UITextField {
if let leftView = tf.leftView as? UIImageView {
leftView.tintColor = .red
}
}
return search
}()
된다!

UISearchBarDelegate를 설정해줘야 한다. 안해주면 그냥 textField와 다름이 없음.. 그래서 얘의 역할이 뭐냐... UITableViewDelegate랑 같다. "UISearchBar 객체의 동작을 관리하기 위한 메서드와 속성을 정의" 한다.
주요 메서드 속성은 다음과 같다. (fromGPT)
- searchBarSearchButtonClicked(_:): 사용자가 검색 버튼을 눌렀을 때 호출됩니다. 이 메서드를 사용하여 검색을 실행하거나 관련 작업을 수행할 수 있습니다.
- searchBarCancelButtonClicked(_:): 사용자가 취소 버튼을 눌렀을 때 호출됩니다. 이 메서드를 사용하여 검색 작업을 취소하거나 관련 작업을 수행할 수 있습니다.
- searchBar(_:textDidChange:): 사용자가 검색 바의 텍스트를 변경할 때 호출됩니다. 이 메서드를 사용하여 실시간 검색 결과를 업데이트하거나 관련 작업을 수행할 수 있습니다.
- searchBar(_:selectedScopeButtonIndexDidChange:): 사용자가 검색 바의 범위 버튼(스코프 버튼)을 변경할 때 호출됩니다. 이 메서드를 사용하여 선택된 스코프에 따라 검색 동작을 조정하거나 관련 작업을 수행할 수 있습니다.
- searchBarShouldBeginEditing(_:): 사용자가 검색 바를 편집하기를 시도할 때 호출됩니다. 이 메서드를 사용하여 검색 바를 편집할 수 있는지 여부를 결정할 수 있습니다.
- searchBarTextDidBeginEditing(_:): 사용자가 검색 바를 편집하기 시작했을 때 호출됩니다. 이 메서드를 사용하여 편집 작업을 시작할 때 필요한 작업을 수행할 수 있습니다.
여기서 나는 서치바의 텍스트가 바뀌었을 때 바로 반영해서 결과를 보여줄수 있게 searchBar(:textDidChange:)와 서치바에서 서치를 눌렀을 때 최신검색어에 데이터를 저장하기 위해 searchBarSearchButtonClicked( searchBar: UISearchBar), 그리고 취소 버튼을 클릭했을 때의 처리를 위한 searchBarCancelButtonClicked(_:)를 사용!
코드는 다음과 같다.
extension SearchViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
print("사용자가 입력한 텍스트: \(searchText)")
searchWord = searchText
if searchText == "" {
fetchTrendingResults()
} else {
updateSearchResults()
}
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
print("사용자가 엔터 키를 눌렀습니다.")
searchBar.resignFirstResponder()
if let keyword = searchBar.text {
searchList.append(keyword)
searchWord = keyword
addLastSearch()
}
resultView.removeFromSuperview()
haveLastSearchList()
lastSearchedCollectionView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
fetchTrendingResults()
searchBar.text = ""
}
}
참고한 문서
https://sueaty.tistory.com/164
https://fomaios.tistory.com/entry/%EC%84%9C%EC%B9%98%EB%B0%94-%EC%BB%A4%EC%8A%A4%ED%85%80%ED%95%98%EA%B8%B0-Custom-UISearchBar
https://sangnam2.tistory.com/entry/Xcode-%EC%8B%9C%EB%AE%AC%EB%A0%88%EC%9D%B4%ED%84%B0-%EC%B6%94%EA%B0%80-iOS-%EB%B2%84%EC%A0%84-%EC%84%A0%ED%83%9D