Start developing iOS 10 - 18 Search Bar and UISearchController with Swift

Keywords: Swift iOS Programming github



Last article Start developing iOS 10 - 17 with Swift using Core Data Core Data is used to store data, this article is to add search function.

Using UISearchController

UISearchController is a concise API for creating search bars and managing search results.
Normally, adding a search bar to a table-based app requires only the following three lines of code. When searchResultsController is nil, the search results are displayed in the current search page in the current style.

searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
tableView.tableHeaderView = searchController.searchBar

Add a search bar for my FoodPin application:

  • Add a variable in Restaurant TableViewController:

     var searchController: UISearchController!
    
  • Initialize in viewDidLoad:

      searchController = UISearchController(searchResultsController: nil)
      tableView.tableHeaderView = searchController.searchBar
    

In this way, the search bar is added, but the search logic is added every day, and the search is ineffective.


Screening content

  • Continue to add a variable in Restaurant TableViewController to store the filter results:

    var searchResults: [RestaurantMO] = []
    
  • Add a screening method:

      func filterContent(for searchText: String) {
          searchResults = restaurants.filter({
          (restaurant) -> Bool in
              
              if let name = restaurant.name {
                  let isMatch = name.localizedCaseInsensitiveContains(searchText)
                  return isMatch
              }
              return false
          })
      }
    

filter is a method of array. It traverses every item of the array to perform operations in the closure, judges whether to delete the corresponding item according to the result, and finally obtains a filtered array.
The localizedCaseInsensitiveContains method is used to determine whether searchText is included in the name (ignoring case)

Update search results

  • Let RestaurantTableViewController "conform" to the UISearchResultsUpdating protocol:

    class RestaurantTableViewController: UITableViewController, NSFetchedResultsControllerDelegate, UISearchResultsUpdating
    
  • Implement the UISearchResultsUpdating protocol:
    updateSearchResults(for:) method, which is called when the search bar is selected and the search word is entered:

    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filterContent(for: searchText)
            tableView.reloadData()
        }
    }
  • Update tableView (: numberOfRowsInSection:). UISearchController has an isActive property to determine the current active state of the search controller.
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchController.isActive {
            return searchResults.count
        } else {
            return restaurants.count
        }
    }
  • Update tableView (: CellForRowAt:). According to the status of UISearchController, it is judged whether to retrieve data from restaurants or search results.
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,
                                                 for: indexPath) as! RestaurantTableViewCell
        
        let restaurant = (searchController.isActive) ? searchResults[indexPath.row] : restaurants[indexPath.row]
        
        cell.nameLabel.text = restaurant.name
        cell.thumbnailImageView.image = UIImage(data: restaurant.image! as Data)
        cell.thumbnailImageView.layer.cornerRadius = 30.0
        cell.thumbnailImageView.clipsToBounds = true
        cell.locationLabel.text = restaurant.location
        cell.typeLabel.text = restaurant.type
        cell.accessoryType = restaurant.isVisited ? .checkmark: .none
        
        return cell
    }
  • Implement a new method to prevent table from sliding in search state.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        if searchController.isActive {
            return false
        } else {
            return true
        }
    }
  • Update prepare(for:) so that segue's data corresponds when it transfers data to detail view.

      destinationController.restaurant = searchController.isActive ? searchResults[indexPath.row] : restaurants[indexPath.row
    
  • Add two lines of code in viewDidLoad:

searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false

The search function is now complete.


Customize the style of the search bar

UISearchBar provides some properties for customization. Add in viewDidLoad:

searchController.searchBar.placeholder = "Search restaurants..."
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor(red: 218.0/255.0, green:
100.0/255.0, blue: 70.0/255.0, alpha: 1.0)

Exercise: Add Address Search

Just change the search function filterContent:

searchResults = restaurants.filter({
        (restaurant) -> Bool in
            
            if let name = restaurant.name, let location = restaurant.location {
                let isMatchName = name.localizedCaseInsensitiveContains(searchText)
                let isMatchLocation = location.localizedCaseInsensitiveContains(searchText)
                if isMatchName || isMatchLocation {
                    return true
                }
                
            }
            return false
        })

Code

Beginning-iOS-Programming-with-Swift

Explain

This article is about learning. appcode A book published on the website <Beginning iOS 10 Programming with Swift> A Record

Catalogue of Series Articles

Posted by T_Hayden on Thu, 10 Jan 2019 00:27:09 -0800