Search code examples
swiftuicollectionviewsearchbar

Search functionality in a collection view


I have a UICollectionView in my app. The UICollectionView is populated with data from a custom object Employee. The Employee object has the following properties:

firstName: String
lastName: String
phoneNumber: String
email: String

I want to add a search functionality to the UICollectionView. Ability to search for employees through their firstName or lastName only. When I search for a particular employee either with their first/last name, if found should display that particular record in the collection view. If not I'd like to show an empty collection view. When nothing is searched it should display all the records in the CollectionView.

As the Employee is a custom object with many properties, I do not know how to go about implementing the search.

I found an article showing how to implement search in a UITableView for an array of String:

 class ViewController: UIViewController, UITableViewDataSource, UISearchBarDelegate {

 @IBOutlet weak var tableView: UITableView!
 @IBOutlet weak var searchBar: UISearchBar!

 let data = ["New York, NY", "Los Angeles, CA", "Chicago, IL", "Houston, TX",
    "Philadelphia, PA", "Phoenix, AZ", "San Diego, CA", "San Antonio, TX",
    "Dallas, TX", "Detroit, MI", "San Jose, CA", "Indianapolis, IN",
    "Jacksonville, FL", "San Francisco, CA", "Columbus, OH", "Austin, TX",
    "Memphis, TN", "Baltimore, MD", "Charlotte, ND", "Fort Worth, TX"]

var filteredData: [String]!

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    searchBar.delegate = self
    filteredData = data
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as UITableViewCell
    cell.textLabel?.text = filteredData[indexPath.row]
    return cell
}

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

// This method updates filteredData based on the text in the Search Box
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    // When there is no text, filteredData is the same as the original data
    // When user has entered text into the search box
    // Use the filter method to iterate over all items in the data array
    // For each item, return true if the item should be included and false if the
    // item should NOT be included
    filteredData = searchText.isEmpty ? data : data.filter { (item: String) -> Bool in
        // If dataItem matches the searchText, return true to include it
        return item.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
    }

    tableView.reloadData()
  }
}

but not sure how to implement it in my case.

Code samples will really help me.

Thanks in advance.


Solution

  • I assume you want to ignore case, too. Try this:

    let lowerSearchText = searchText.lowercased()
    filteredData = searchText.isEmpty ? data : data.filter { employee -> Bool in
        return employee.firstName.lowercased().hasPrefix(lowerSearchText) || employee.lastName.lowercased().hasPrefix(lowerSearchText)
    }
    

    You may want to extend this to support other locales (match e to é) etc.