iOS17 にしたら tableHeaderView に入れた searchController がバグって表示されるようになってしまった。
iOS17めっちゃバグるやん pic.twitter.com/DO7ewmgVBh
— スターホシ (@star__hoshi) October 5, 2023
最初は hidesNavigationBarDuringPresentation を true にしたらいい感じにはなったんだけど、NavigationBar が隠れたまま次の画面に遷移すると NavigationBar が消えたままになってしまいダメだった。
解決するために試行錯誤したが、結局は UISearchController を使うのをやめて UISearchBar を使うことで解決した。
Before
final class ViewController: UIViewController { let searchController = UISearchController(searchResultsController: nil) override func viewDidLoad() { searchController.searchResultsUpdater = self searchController.obscuresBackgroundDuringPresentation = false searchController.hidesNavigationBarDuringPresentation = false searchController.searchBar.placeholder = "placeholder" searchController.delegate = self searchController.searchBar.delegate = self tableView.tableHeaderView = searchController.searchBar } extension ViewController: UISearchResultsUpdating, UISearchControllerDelegate { func updateSearchResults(for searchController: UISearchController) { print(searchController.searchBar.text ?? "") } } extension ViewController: UISearchBarDelegate { func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in print(keyword) } return true } }
After
final class ViewController: UIViewController { let searchBar = UISearchBar() override func viewDidLoad() { searchBar.delegate = self searchBar.placeholder = "placeholder" searchBar.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:56) tableView.sectionHeaderTopPadding = 0 tableView.tableHeaderView?.frame = searchBar.frame tableView.tableHeaderView = searchBar } extension ViewController: UISearchBarDelegate { func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in print(searchBar.text!) } return true } func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in print(searchBar.text!) } } func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() } func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() } func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) { searchBar.setShowsCancelButton(true, animated: true) } func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { searchBar.setShowsCancelButton(false, animated: true) } }
補足
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100))
はこれ
おわり
iOSはNavigationBarと検索バー周りはぶっ壊れがちなので大変。
iOS13 の時も苦しんでいた。
iOS13モーダルとSearchControllerの相性悪いというかNavigationBarとSearchBarもむずいしとにかくむずい...
— スターホシ (@star__hoshi) 2019年12月15日