-0.3 C
New York
Wednesday, April 9, 2025

ios – Proper approach to present a UISearchController on a bar button icon faucet


My finish objective is to have the ability to have constant search expertise throughout each iPhone and iPad.

The expertise I’m after is to set off the UISearchResultsController on a bar button faucet slightly than exhibiting the search bar within the UINavigationBar

One thing like this:

SwiftUI UIKit custom search controller transition experience

What I’ve completed to realize this:

#1 – I name the next code from my View Controller so as to initialize a UISearchResultsController however conceal the search bar initially and set off it utilizing a bar button merchandise

// Known as from viewDidLoad
personal func configureSearchExperience() {
    let picture = UIImage(named: "searchIconName")
    
    searchController = createSearchController()
    searchController?.searchBar.placeholder = searchPlaceHolder
    searchController?.searchBar.setImage(picture, for: .search, state: .regular)
    searchController?.searchBar.autocapitalizationType = .none
    searchController?.searchBar.isHidden = true
    
    navigationItem.searchController = nil
    navigationItem.hidesSearchBarWhenScrolling = false
}

personal func createSearchController() -> UISearchController {
    let viewController =  UIHostingController(rootView: SearchResultsSwiftUIView())
    
    let search = CustomSearchController(searchResultsController: viewController)
    search.delegate = self
    search.showsSearchResultsController = true
    search.obscuresBackgroundDuringPresentation = true
    search.searchBar.delegate = self
   
    return search
}

// Known as from viewDidLoad
personal func addBarButtons() {
    let settingsButton = createButton(imageName: settingsIconName,
                                      motion: #selector(showSettings),
                                      accessibilityLabel: viewModel.settingsAccessibilityIdentifier)
    
    let searchButton = createButton(imageName: searchOutlineIconName,
                                    motion: #selector(launchSearchExperience),
                                    accessibilityLabel: viewModel.searchAccessibilityIdentifier)
    
    let stackView = UIStackView(arrangedSubviews: [searchButton, settingsButton])
    stackView.axis = .horizontal
    stackView.spacing = viewModel.barButtonInterItemSpacing
    
    navigationItem.rightBarButtonItem = UIBarButtonItem(customView: stackView)
}

personal func createButton(imageName: String, motion: Selector, accessibilityLabel: String) -> UIButton {
    let button = UIButton(sort: .system)
    
    if let picture = UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal) {
        button.setImage(picture, for: .regular)
    }
    
    button.addTarget(self, motion: motion, for: .touchUpInside)
    button.accessibilityLabel = accessibilityLabel
    
    return button
}

@objc func launchSearchExperience() {
    navigationItem.searchController = searchController
    
    // A brief delay prevents occasional UI glitches when activating the search controller instantly after including it
    // to the navigation merchandise. The 0.1s delay is an empirically chosen worth that balances responsiveness and stability.
    // It was additionally urged in: https://stackoverflow.com/q/27951965/1619193
    
    let searchActivationDelay = 0.1
    
    DispatchQueue.foremost.asyncAfter(deadline: .now() + searchActivationDelay) { [weak self] in
        self?.searchController?.isActive = true
        self?.searchController?.becomeFirstResponder()
    }
}

#2 – That is the customized SearchResultsController accountable to point out the search bar ONLY when the UISearchResultsController is activated:

class CustomSearchController: UISearchController {
    override func viewWillAppear(_ animated: Bool) {
        tremendous.viewWillAppear(animated)
        searchBar.isHidden = false
        searchBar.becomeFirstResponder()
    }

    override func viewWillDisappear(_ animated: Bool) {
        tremendous.viewWillDisappear(animated)
        searchBar.isHidden = true
    }
}

Collectively this offers me the expertise I need for probably the most half on iPhones, nevertheless, on iPad, it will get damaged within the state of affairs once I go to the element view from one of many search outcomes after which swipe to return again, right here is an illustration of this:

#1 – We begin the icon within the nav bar

iPad bar button items for UISearchResultsController

#2 – Search outcomes controller is activated

iPad UISearchResultsController

#3 – Getting back from particulars display screen display screen messes this up

iPad UISearchResultsController animation issue

#4 – Slowing the swipe again animation reveals it’s advantageous until the final second after which breaks

iPad UISearchResultsController animation issue

iPhone doesn’t have this situation and if I faucet again and return, we do not need this situation.

Solely once I swipe to return again, we have now this situation.

Any concept what might be unsuitable.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles