Ege Akkaya
Ege Akkaya

Reputation: 186

Swift search navigation item not updating

I created a search navigation bar for users to easily choose the entry they want in a long list. Say if user enters "a", it will only show the user entries starting with "a". However, nothing appears when I type anything on the search bar. I entered this code in viewDidLoad.

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    navigationItem.searchController = UISearchController(searchResultsController: nil)
    navigationItem.hidesSearchBarWhenScrolling = false

}

And below I have my typical tableview functions.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
    return 22
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
    identifiers = ["Adana","Ankara","Antalya","Balikesir","Bursa","Denizli","Diyarbakir","Eskisehir","Gaziantep","Hatay","Icel","Istanbul","Izmir","Kayseri","Kocaeli","Konya","Manisa","Sakarya","Samsun","Sivas","Trabzon","Sanliurfa"]
    //let cell = tableView.dequeueReusableCell(withIdentifier: "CellTwo")
    //cell?.textLabel!.text = identifiers[indexPath.row]
    //return cell!
    let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "CellTwo")
    cell.textLabel!.text = identifiers[indexPath.row]
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){


    // here you can use someThing like an array of your segue identifiers
    selectedParamTwo = tableView.cellForRow(at: indexPath)!.textLabel!.text!
    self.performSegue(withIdentifier: "seg2", sender: self)

}

Moreover, I can't seem to find a way to change the placeholder in the search bar. I'd appreciate any help. Thank you in advance!

Upvotes: 0

Views: 311

Answers (3)

Joshua Wolff
Joshua Wolff

Reputation: 3352

It sounds like you are merely adding the search bar in your storyboard and expecting it to work. When you type in the search bar, you need to tell it what to do. In order to do this, you need proper delegates and search implementations.

Check out these links for more information:

Add this at the top of your class for an internal global that your class can use anywhere:

var searchController : UISearchController! = UISearchController(searchResultsController: nil)

Now implement the proper protocols:

extension YourTableViewController : UISearchControllerDelegate, UISearchBarDelegate, UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        if let text : String = searchController.searchBar.text {
            // Process data here in some kind of for loop.
            self.tableView.reloadData()
        }
    }
}

More on how this works here: https://developer.apple.com/documentation/uikit/uisearchresultsupdating

Put this function in your class or somewhere else. Just make sure you can call it as you please. Feel free to use this code and modify it. You can use this single function in a struct (if so, mark it as "static") and call it from wherever to make your search bar implementation consistent across your application.

func setUpSearchController(for searchController: UISearchController, placeHolder: String, tableViewController: UITableViewController, searchControllerDelegate: UISearchControllerDelegate, searchUpdaterDelegate: UISearchResultsUpdating, searchBarDelegate: UISearchBarDelegate) {
    // SearchBar text
    let textFieldInsideUISearchBar = searchController.searchBar.value(forKey: "searchField") as? UITextField /* Do not edit this key. This is not where you put your own placeholder. Put your placeholder in the function call. */
    textFieldInsideUISearchBar?.font = Constants.MAIN_FONT /* Add your font here or add as a parameter */
    // SearchBar placeholder
    let textFieldInsideUISearchBarLabel = textFieldInsideUISearchBar!.value(forKey: "placeholderLabel") as? UILabel /* Do not edit this key. This is not where you put your own placeholder. Put your placeholder in the function call. */
    textFieldInsideUISearchBarLabel?.font = UIFont.systemFont(ofSize: 15.0) /* Customize or add your font here or add as a parameter */
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.searchBar.barStyle = .black
    searchController.searchBar.tintColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1) /* Customize or add your own color as a parameter*/
    searchController.searchBar.delegate = searchBarDelegate
    searchController.searchBar.keyboardAppearance = UIKeyboardAppearance.light
    searchController.obscuresBackgroundDuringPresentation = false
    searchController.searchBar.placeholder = placeHolder
    searchController.definesPresentationContext = true
    searchController.searchResultsUpdater = searchUpdaterDelegate
    tableViewController.navigationItem.titleView = searchController.searchBar
    tableViewController.definesPresentationContext = true
}

In order to call the function, call the function like this (assuming you put the function in your class..):

self.setUpSearchController(searchController: self.searchController, placeHolder: "PlaceHolder Text", tableViewController: self, searchControllerDelegate: self, searchUpdaterDelegate: self, searchBarDelegate: self)

If you can't see the search controller, make sure your navigation bar is not hidden and also make sure that you're table view is embedded in a navigation controller.

Good luck!

Upvotes: 0

Kuldeep
Kuldeep

Reputation: 4552

Try this Code. You need to add UISearchBar delegate to work it.

You need to correct below thing.

1. You return static 22 rows in numberOfRowsInSection which it not proper. First you need to identify wether user search anything or not and based on that you need to return data.

2. You define identifiers array in cellForRowAt. Same as numberOfRowsInSection you need to return data by checking wether user search anything or not.

You need to do like below

First define 2 array globally 1st is your identifier array and 2nd is your searcher data array

var identifiers = [String]()
var arrSearcherData = [String]()
var isSearching: Bool = false    // Add this to identify wether user is searching data or not

viewDidLoad()

override func viewDidLoad() {
    super.viewDidLoad()
    identifiers = ["Adana","Ankara","Antalya","Balikesir","Bursa","Denizli","Diyarbakir","Eskisehir","Gaziantep","Hatay","Icel","Istanbul","Izmir","Kayseri","Kocaeli","Konya","Manisa","Sakarya","Samsun","Sivas","Trabzon","Sanliurfa"]

    navigationItem.searchController = UISearchController(searchResultsController: nil)
    navigationItem.searchController?.searchBar.delegate             = self
    navigationItem.searchController?.searchBar.showsCancelButton    = true
    navigationItem.hidesSearchBarWhenScrolling                      = false
    self.definesPresentationContext                                 = true
}

Your TableView Delegate & DataSource

extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if isSearching {
            return arrSearcherData.count
        }
        return identifiers.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell(style: .value1, reuseIdentifier: "Cell")

        if isSearching {
            cell.textLabel?.text = arrSearcherData[indexPath.row]
        }
        else {
            cell.textLabel?.text = identifiers[indexPath.row]
        }

        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

    }
}

Your SearcherBar Delegate

//MARK:- UISearchBar Delegate
extension ViewController: UISearchBarDelegate {
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        self.tblvw.reloadData()

        if searchText.count == 0 {
            isSearching = false
        }
        else {
            isSearching = true
            arrSearcherData = identifiers.filter { $0.contains(searchText) }
        }
        self.tblvw.reloadData()
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = false
        searchBar.text = ""
        searchBar.resignFirstResponder()
        isSearching = false
        self.tblvw.reloadData()
    }
}

Upvotes: 2

ranjeet
ranjeet

Reputation: 51

By above Information, it's not clear what's wrong in code. But can please check whether you have call "searchBarShouldBeginEditing" delegate in the code.

Within this delegate you need to write a code which will trigger search entry.

Upvotes: 0

Related Questions