1

Here is my view with UISearchBar in my navigationbar:

enter image description here

I want it get focussed automatically when my view is loaded. I tried a few ways based on this question. But none is working. I have to click the searchbar to make it focussed.

enter image description here

This is one of my code:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    self.searchController.isActive = true

    DispatchQueue.main.async { [unowned self] in
        self.searchController.searchBar.becomeFirstResponder()
    }
}

Somebody mentioned the searchController should be active after becomeFirstResponder. I tried this:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    DispatchQueue.main.async { [unowned self] in
        self.searchController.searchBar.becomeFirstResponder()
        self.searchController.isActive = true
    }
}

The keybord did come out this time. But I can't key in anything in my search bar.

Any idea? Thanks.

Community
  • 1
  • 1
Bagusflyer
  • 12,675
  • 21
  • 96
  • 179

2 Answers2

7

I follow the suggestion and recreate my project. It works then. My code:

class SearchViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchResultsUpdating, UISearchControllerDelegate, UISearchBarDelegate {

 ......

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    searchController.isActive = true
}

func didPresentSearchController(_ searchController: UISearchController)    {
    DispatchQueue.main.async { [unowned self] in
        self.searchController.searchBar.becomeFirstResponder()
    }
}

Has to put becomeFirstRespnder in main queue, otherwise the keyboard will not be shown automatically.

Bagusflyer
  • 12,675
  • 21
  • 96
  • 179
0

I could focus the search bar whenever it is appear with the following code. Hope if would be helped.

And I have compared calling the become first responder inside viewWillAppear and viewDidAppear, it only worked when you call it inside viewWillAppear. But I am not quite understand why this happened. That maybe the reason why you can't type anything inside your searchbar.

PS: I think your DispatchQueue.main.async is not necessary inside viewDidAppear. It always be called in the main queue.

//
//  TestSearchbarFocus.swift
//  SwiftPlayground
//
//  Created by Enix Yu on 31/10/2016.
//  Copyright © 2016 RobotBros. All rights reserved.
//

import UIKit


class TestSearchbarFocus: UITableViewController, UISearchResultsUpdating {

    var searchController : UISearchController!

    let data = ["ABC", "BBC", "CCD", "Enix", "Peter", "Earth"]
    var displayData = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self
        searchController.dimsBackgroundDuringPresentation = false
        searchController.hidesNavigationBarDuringPresentation = false
        definesPresentationContext = true
        navigationItem.titleView = searchController.searchBar
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        searchController.active = true
        searchController.searchBar.becomeFirstResponder()
    }

    func filterDataForSearchText(text: String){
        displayData = data.filter({
            (item) -> Bool in
            item.lowercaseString.containsString(text.lowercaseString)
        })

        tableView.reloadData()
    }

    func updateSearchResultsForSearchController(searchController: UISearchController) {
        filterDataForSearchText(searchController.searchBar.text!)
    }

    // MARK : UITableViewDataSource/Delegate

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchController.active && searchController.searchBar.text != "" {
            return displayData.count
        }

        return data.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
        if searchController.active && searchController.searchBar.text != "" {
            cell.textLabel?.text = displayData[indexPath.row]
        } else {
            cell.textLabel?.text = data[indexPath.row]
        }
        return cell
    }
}

PS: I am using swift 2 + Xcode 7.3.1

Enix
  • 4,415
  • 1
  • 24
  • 37