Cannot set searchBar as firstResponder

前端 未结 21 1827
别跟我提以往
别跟我提以往 2020-11-30 01:33

I have a searchBar I\'m setting in a tableviewcontroller. i\'ve referenced this similar question UISearchBar cannot become first responder after UITableView did re-appear bu

相关标签:
21条回答
  • 2020-11-30 02:27

    I battled with this for a while but got it working by:

    • Initializing the searchController in viewDidLoad()
    • Setting active = true in viewDidAppear()
      • This triggers didPresentSearchController() in the UISearchControllerDelegate extension.
    • Setting searchBar.becomeFirstResponder() in didPresentSearchController()

    Here's the full example, it uses Google Maps Autocomplete.

    class myViewController: UIViewController {
    
        // MARK: Variables
    
        var resultsViewController: GMSAutocompleteResultsViewController?
        var searchController: UISearchController?
        var resultView: UITextView?
    
        // MARK: Outlets
    
        @IBOutlet var myView: UIView!
    
        // MARK: View Methods
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            resultsViewController = GMSAutocompleteResultsViewController()
            resultsViewController?.delegate = self
    
            searchController = UISearchController(searchResultsController: resultsViewController)
            searchController?.delegate = self
            searchController?.searchResultsUpdater = resultsViewController
    
            searchController?.searchBar.prompt = "Search for a Place"
            searchController?.searchBar.placeholder = "place name"
            searchController?.searchBar.text = ""
            searchController?.searchBar.sizeToFit()
    
            searchController?.searchBar.returnKeyType = .Next
            searchController?.searchBar.setShowsCancelButton(true, animated: false)
    
            myView.addSubview((searchController?.searchBar)!)
        }
    
        override func viewDidAppear(animated: Bool) {
            super.viewDidAppear(true)
            searchController?.active = true
        }
    
        // MARK: GMSAutocompleteResultsViewControllerDelegate Extension
    
        extension myViewController: GMSAutocompleteResultsViewControllerDelegate {
    
            func resultsController(resultsController: GMSAutocompleteResultsViewController,
                           didAutocompleteWithPlace place: GMSPlace) {
                searchController?.active = false
                // Do something with the selected place.
                print("Place name: ", place.name)
                print("Place address: ", place.formattedAddress)
                print("Place attributions: ", place.attributions)
            }
    
            func resultsController(resultsController: GMSAutocompleteResultsViewController,
                           didFailAutocompleteWithError error: NSError){
                // TODO: handle the error.
                print("Error: ", error.description)
            }
    
            // Turn the network activity indicator on and off again.
            func didRequestAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController) {
                UIApplication.sharedApplication().networkActivityIndicatorVisible = true
            }
    
            func didUpdateAutocompletePredictionsForResultsController(resultsController: GMSAutocompleteResultsViewController) {
                UIApplication.sharedApplication().networkActivityIndicatorVisible = false
            }
        }
    
        extension myViewController: UISearchControllerDelegate {
    
            func didPresentSearchController(searchController: UISearchController) {
                self.searchController?.searchBar.becomeFirstResponder()
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 02:28

    The solution with - (void)didPresentSearchController:(UISearchController *)searchController did not work, since this delegate method is called only when the user taps on the search bar...

    However, this solution did work:

    - (void) viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        [self performSelector:@selector(showKeyboard) withObject:nil afterDelay:0.1];
    }
    
    - (void) showKeyboard
    {
        [self.searchController.searchBar becomeFirstResponder];
    }
    

    Swift 3

    delay(0.1) { self.searchController.searchBar.becomeFirstResponder() }
    
    func delay(_ delay: Double, closure: @escaping ()->()) {
        let when = DispatchTime.now() + delay
        DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
    }
    
    0 讨论(0)
  • 2020-11-30 02:28

    To me, there’s a quite big lag when using viewDidAppear. It can be better to use becomeFirstResponder asynchronously in viewDidLoad (tested with iOS 10, Swift 3):

    override func viewDidLoad() {
        super.viewDidLoad()
    
        DispatchQueue.main.async {
            searchController.searchBar.becomeFirstResponder()
        }
    }
    
    0 讨论(0)
提交回复
热议问题