Swift 5 & iOS 13 UISearchController wrong presenting and dismissing behaviour
Asked Answered
M

2

7

While i was updating my project to iOS 13 i faced with unusual issue. I have logic for showing and handling some UISearchController actions (code below), all parts were working perfectly in iOS 11 & 12.

My task was to add search button at navigation bar to show UISearchController after button action.

But in iOS 13, i got 2 issues:

Code that invokes from button action

func showSearch() {
        let searchResultsController = LUSearchResultsViewController()...
        let searchController = UISearchController(searchResultsController: searchResultsController)
        searchController.delegate = self
        searchController.searchResultsUpdater = searchResultsController
        navigationItem.searchController = searchController
        definesPresentationContext = true
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            searchController.isActive = true
        }
}

Only one solution helps me to show search controller without any diffs from previous iOS versions.

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            searchController.isActive = true
}

Code that works on iOS 13, on iOS 11 and 12 code works without asyncAfter

Code that helps me to hide UISearchController and set navigation bar initial state in iOS 11 and 12, and not in 13. After tapping cancel on SearchBar, UISearchController begins to call delegate methods.

  //MARK: UISearchControllerDelegate


    public func willDismissSearchController(_ searchController: UISearchController) {
         self.navigationItem.searchController = nil
    }

BUT

After setting navigationItem.searchController = nil didPresentSearchController calls twice and not only UISearchController dismissed, but whole UIViewController hierarchy right to UIWindow. Or if i add asyncAfter here i get normal dismiss with expanded nav bar height, that i don't need.

SO

  1. I think that asyncAfter in a dog-nail, how would you solve this problem?
  2. How can i dismiss UISearchController correctly?
Masoretic answered 24/9, 2019 at 12:55 Comment(1)
UISearchController in iOS13 unfortunately has several issues in respect to its behavior in earlier versions, another example is in the display characteristics of the SearchResultsController - it's not clear to me whether these are bugs or expected behavior.Salmon
B
1

This issue is happening on iOS 13

Add searchController.extendedLayoutIncludesOpaqueBars = true

as well as

`
extension SearchViewController:UISearchControllerDelegate{
    func willPresentSearchController(_ searchController: UISearchController) {
        if #available(iOS 13, *){
            self.navigationController?.navigationBar.isTranslucent = true
        }
    }
    func willDismissSearchController(_ searchController: UISearchController) {
        if #available(iOS 13, *){
            self.navigationController?.navigationBar.isTranslucent = false
        }
    }
}
`
Beatnik answered 14/12, 2019 at 18:50 Comment(0)
P
0

I can help you with the first part.

Instead of doing the async part you can use this:

searchController.searchBar.layoutIfNeeded()        
searchController.isActive = true

The SearchController isn't ready at that particular moment and it needs to layout first before it can become active.

By layout-ing the searchBar we force this and it will only trigger if there's something to layout.

Pendergast answered 26/9, 2019 at 10:50 Comment(1)
deejfit thanks for reply, i`ve tried to use solution with searchBar layout, but only asyncAfter works fine (Masoretic

© 2022 - 2024 — McMap. All rights reserved.