[RESOLU] Faire une recherche dans une tableview dont la source est un object Realm

Bonjour à tous !

Est ce que quelqu’un à déjà utilisé une SearchBar ou SearchBar Controller avec Realm?

Premièrement j’ai pas encore saisi la nuance entre la simple SearchBar et SearchBar and Display Controller du coup c’est assez compliqué de trouver les infos utiles pour avancer sur le sujet… Je n’arrive absolument pas à comprendre comment l’utiliser.

Deuxièmement ce que je souhaite faire c’est rechercher un NOM dans une tableView pleine de NOMS, la tableView est chargée à partir d’un objet Realm.

@mbritto A quand le cours sur la SearchBar ? :wink:

Merci à celui qui pourrait m’aider !

Hello,

Alors, comme tu sais, je n’utilise pas Realm (:slight_smile:). Par contre, j’ai déjà implémenté une SearchBar.
Tu as donc un viewcontroller avec la search bar et aussi un search result controller qui sera le contrôleur du résultat de ta recherche (l’affichage).
Dans mon cas, je faisais une recherche de contacts

Dans mon view controller, si je filtre les informations qui sont importants pour la recherche (attention, ça m’étonnerait que ça compile dans l’état, c’est juste pour te donner des indications) :

import UIKit

class ContactsViewController: UITableViewController, UISearchBarDelegate {
    
    var searchController = UISearchController(searchResultsController: ContactsSearchResultsController())
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupSearchController()
    }

}

// Setting up the contact search bar
extension ContactsViewController: UISearchResultsUpdating, UISearchControllerDelegate{


    func setupSearchController(){
        
        searchController = UISearchController(searchResultsController: storyboard?.instantiateViewController(withIdentifier: "nav-contacts-search"))
        searchController.searchResultsUpdater = self
        definesPresentationContext = true
        if #available(iOS 11.0, *) {
            self.navigationItem.searchController = searchController
        }
    }

    // Search did change
    func updateSearchResults(for searchController: UISearchController) {
        if let searchResultsController = (searchController.searchResultsController as? UINavigationController)?.viewControllers[0] as? ContactsSearchResultsController{
            searchResultsController.data = fullNameContacts.filter{ ($0.lowercased().contains(searchController.searchBar.text?.lowercased() ?? "")) }
        }
}
}

Sachant que iOS11 permet quelques petites présentations sympa des résultats, tu verras que je n’ai pas encore géré le cas où l’utilisateur n’est pas sur iOS11 ^^

Et mon searchresultscontroller

import UIKit

class ContactsSearchResultsController: UITableViewController {
        
    public var data = [String](){
        didSet{
            tableView.reloadData()
        }
    }
        
    override func viewDidLoad() {
        super.viewDidLoad()
        self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0)
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "result-contact-cell", for: indexPath)
        cell.textLabel?.text = data[indexPath.row].components(separatedBy: "|")[0]
        cell.detailTextLabel?.text = data[indexPath.row].components(separatedBy: "|")[1]
        return cell
    }
}

Mon cas étant un peu spécial car j’ai dû rentrer tous les contacts dans un tableau pour le faire passer à la recherche et ensuite faire du tri dedans selon un caractère spécial que j’avais choisi (le pipe).

Donc à voir si ça peut t’aider :slight_smile:

Je viens de le refaire avec MapKit dans mon projet (une barre de recherche d’adresse) donc je peux aussi t’aider là-dessus si tu veux !

ok merci je vais mettre en pratique, je comprend mieux l’histoire du searchview controller.
Mais un cours de la part de Max ne sera pas inutile je pense… A bon entendeur…

J’avoue que le search avec son search result controller peuvent être complexes à prendre en main au départ.
Notez qu’apple ne le dit pas clairement dans la doc mais il est possible d’utiliser la search bar sans pour autant utiliser le search result controller.
La search bar avec delegation peut suffire dans pleins de cas, surtout avec Realm où on peut facilement remplacer la requête de la liste d’objets.

Ouaip, surtout, là ce qui est chiant c’est que je trouve qu’il y a une grosse amélioration de la searchBar avec l’arrivée d’iOS11 notamment sur la définition de la searchBar avec

navigationItem.searchController = resultSearchController

Par contre, ce qui est vraiment pénible à faire, c’est d’essayer de reproduire le même résultat pour les non iOS11. J’avais repoussé les // Fallback on earlier versions à plus tard et, avec le recul, j’aurais dû le faire directement tant que c’était chaud dans ma tête car maintenant j’en chie à repasser sur chaque if #available(iOS 11.0, *).

Je saurai pour la prochaine fois :slight_smile:

Salut @schtipoun
je n’ai finalement pas suivi ton exemple (avec le searchController) j’ai juste utilisé une searchBar et fait une extension de mon ViewController pour gérer tout ce qui concerne cette searchBar, quelques fonctions dans mon RealmManager et le tour est joué.

Dans le RealmManager il faut faire une fonction qui va filtrer ton objet Realm pour en recréer un nouveau à chaque fois qu’une lettre est tapée dans la searchBar.

Pas évident d’expliquer tout ça par écrit… mais ça marche très très bien
c’est là où l’on voit la performance de Realm dont parlé @mbritto.
Une recherche d’un nom parmi plus de 3000 noms dans la base de donnée se fait instantanément lettre aprés lettre

    extension ViewController: UISearchBarDelegate {
        func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
            isSearching = true
        }
        
        func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
            isSearching = false
        }

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)

{
            if let newCustomers = _customers?.setFileteredCustomersList(searchedText: searchText) {
                _customers?._filteredCustomersList = newCustomers
            }
            ui_customersList.reloadData()
        }
    }

    class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    ...
    }

Mission accomplie je passe le sujet en RESOLU

Merci à vous d’avoir éclairé ma lanterne, mais je suis quand même curieux d’approfondir la partie SearchBarController

1 « J'aime »

Tant que tu as pu arriver à tes fins, c’est bien là le principal :slight_smile: