29. Oktober 2019

UITableView filtern mit UISearchController

Dieses Tutorial zeigt, wie Daten in einem UITableViewController mit der UISearchController-Klasse gefiltert bzw. durchsuchbar gemacht werden können:

Gefilterte Ergebnisliste
  1. Verwende für dieses Tutorial die aktuelle Version von Xcode (dieses Tutorial wurde zuletzt getestet am 29. Oktober 2019 mit Xcode 11.1).

  2. Verwende das Projekt aus dem UITableViewController-Tutorial oder lade das zugehörige Beispielprojekt Countries. Dieses enthält einen UITableViewController der Daten aus einem Swift-Array zur Anzeige bringt:

    UITableView: Daten in Tabelle
  3. Öffne das Storyboard des Projektes und füge mit Embed in » Navigation Controller ein Navigations-Controller hinzu (die Bar für die Suche wird in der Navigations-Bar angezeigt):

    Storyboard: Embed in Navigation Controller
  4. Öffne CountriesTableViewController.swift und ergänze die Klasse um eine Methode setupSearch. Erstelle einen UISearchController und halte ihn in einer Controller-Eigenschaft. Implementiere setupSearch so, dass der SearchController beim navigationItem registriert wird:

    class CountriesTableViewController: UITableViewController {
    
        // ...
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.setupSearch()
        }
    
        // MARK: - Search
    
        private var searchController = UISearchController(searchResultsController: nil)
    
        func setupSearch() {
        self.navigationItem.searchController = searchController
    }
    
       // ...
    }

    Dem UISearchController kann ein zweiter ViewController für die Ergebnisanzeige übergeben werden - wird nil als searchResultsController übergeben, erfolgt die Darstellung durch den Controller selbst.

  5. Lass den CountriesTableViewController das UISearchResultsUpdating-Protokoll implementieren und registriere ihn als searchResultsUpdater beim searchController. Implementiere die updateSearchResults-Methode so, dass die Suchergebnisse mit der filter-Methode gefiltert werden und das UITableView aktualisiert wird:

    class CountriesTableViewController: UITableViewController, UISearchResultsUpdating {
    
        var countries = Country.allCountries
        
        // ...
    
        private var searchController = UISearchController(searchResultsController: nil)
    
        func setupSearch() {
            self.navigationItem.searchController = self.searchController
            // Aktualisierung der Suchergebnisse via UISearchResultsUpdating-Protokoll
    searchController.searchResultsUpdater = self
        }
        
        func updateSearchResults(for searchController: UISearchController) {
        // Länderliste filtern, wenn ein Suchtext eingegeben wird
        // Ansonsten alle Länder anzeigen - damit wird auch der Cancel-Fall behandelt
        if let searchText = searchController.searchBar.text, !searchText.isEmpty {
            countries = Country.allCountries.filter { (country) in
                country.name.localizedCaseInsensitiveContains(searchText)
            }
        }
        else {
            countries = Country.allCountries
        }
        
        // UITableView aktualisieren
        self.tableView.reloadData()
    }
    
    }
  6. Teste die App, scrolle in der Liste nach oben um das Suchfeld einzublenden und prüfe, dass die Ergebnisse korrekt gefiltert angezeigt werden:

    Ergebnisanzeige
  7. Optional kannst Du die Implementierung in setupView noch so anpassen, das die Suchleiste immer sichtbar ist und die Suchergebnisse nicht ausgegraut erscheinen:

    // Such-Bar immer sichtbar machen
    self.navigationItem.hidesSearchBarWhenScrolling = false
    
    // Ausgegraute Darstellung der Suchergebnisse deaktivieren
    searchController.obscuresBackgroundDuringPresentation = false