UISearchController: afficher les résultats même lorsque la barre de search est vide

Si je comprends bien, le comportement par défaut de UISearchController est:

  1. En tapant sur la barre de search, l'arrière-plan est grisé et le button «Annuler» s'affiche. SearchResultsController n'est pas affiché jusqu'à ce point.
  2. SearchResultsController est affiché uniquement si la barre de search n'est pas vide.

Je veux afficher SearchResultsController même lorsque la barre de search est vide mais sélectionnée (c'est-à-dire est le cas 1 ci-dessus).

Autrement dit, au lieu de la gradation d'arrière-plan, j'aimerais montrer les résultats de search.

Y a-t-il un moyen de faire cela?

Plus de clarification:

Je n'utilise pas UISearchController pour filterr les résultats affichés sur la vue sur laquelle il est affiché, mais d'autres résultats non liés. Ce sera comme ce que facebook fait sur son 'fil d'actualité'. En tapant sur la barre de search, vous affichez d'abord les suggestions de search, puis, lorsque nous commençons à les modifier, affiche les résultats de search qui ne sont peut-être pas liés au fil de nouvelles.

Si votre barre de search est active mais n'a pas de text, les résultats tableView sous-jacents sont affichés. C'est le comportement embedded, et la raison pour laquelle searchResultsController est caché pour cet état.

Pour changer le comportement lorsque la search est active mais pas le filtrage, vous devez afficher le searchResultsController quand il est normalement encore caché.

Il existe peut-être un bon moyen d'y parvenir via <UISearchResultsUpdating> et updateSearchResultsForSearchController: Si vous pouvez le résoudre via le protocole, c'est la meilleure façon de procéder.

Si cela ne vous aide pas, il vous rest à pirater le comportement embedded. Je ne reorderais pas ou ne comptais pas dessus, et ça va être fragile, mais voici une réponse si vous choisissez cette option:

  1. Assurez-vous que votre tableViewController est conforme à <UISearchControllerDelegate> et ajoutez

    self.searchController.delegate = self;

  2. Implémentez willPresentSearchController:

     - (void)willPresentSearchController:(UISearchController *)searchController { dispatch_async(dispatch_get_main_queue(), ^{ searchController.searchResultsController.view.hidden = NO; }); } 

    Cela rend le searchResultsController visible après que son UISearchController mis à caché.

  3. Implémenter didPresentSearchController:

     - (void)didPresentSearchController:(UISearchController *)searchController { searchController.searchResultsController.view.hidden = NO; } 

Pour une meilleure façon de contourner le comportement embedded , voir la réponse de Malhal .

Vous pouvez simplement implémenter le protocole UISearchResultsUpdating et définir l'affichage du controller de résultats pour qu'il updateSearchResultsForSearchController toujours dans updateSearchResultsForSearchController :

  func updateSearchResultsForSearchController(searchController: UISearchController) { // Always show the search result controller searchController.searchResultsController?.view.hidden = false // Update your search results data and reload data .. } 

Cela fonctionne parce que la méthode est appelée même lorsque la barre de search est activée, sans aucun text.

J'ai essayé la solution PetahChristian, le résultat de la précharge est apparu lorsque nous avons d'abord focalisé la barre de search, mais quand nous entrons quelque chose, puis l'effaceons, les résultats de la précharge ne réapparaissent pas.

Je suis venu avec une autre solution. Nous avons seulement besoin d'append un délégué dans SearchResultsController et de l'appeler quand notre searchController.searchBar.text est vide. Quelque chose comme ça:

SearchResultsController:

 protocol SearchResultsViewControllerDelegate { func reassureShowingList() -> Void } class FullSearchResultsViewController: UIViewController, UISearchResultsUpdating{ var delegate: SearchResultsViewControllerDelegate? ... func updateSearchResultsForSearchController(searchController: UISearchController) { let query = searchController.searchBar.text?.sortingm() if query == nil || query!.isEmpty { ... self.delegate?.reassureShowingList() ... } ... } 

Et dans le controller contient le SearchController, nous ajoutons notre délégué:

 self.searchResultsController.delegate = self func reassureShowingList() { searchController.searchResultsController!.view.hidden = false } 

Avec des choses délicates comme celle-ci, je recommand l'approche du marteau de masse! C'est détecter quand quelque chose essaie de le cacher et quand c'est le cas, le changer. Cela peut être fait via KVO (Key Value Observing). Cela fonctionnera quoi qu'il arrive, sans avoir à gérer toutes les subtilités de la barre de search. Désolé, le code est compliqué mais KVO est une API de style plus ancien mais mon code suit la pratique recommandée. Dans votre SearchResultsViewController mettez ceci:

 static int kHidden; @implementation SearchResultsViewController -(void)viewDidLoad{ [super viewDidLoad]; [self.view addObserver:self forKeyPath:@"hidden" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:&kHidden]; } - (void)observeValueForKeyPath:(NSSsortingng *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // if it was our observation if(context == &kHidden){ // if the view is hidden then make it visible. if([[change objectForKey:NSKeyValueChangeNewKey] boolValue]){ self.view.hidden = NO; } } else{ // if necessary, pass the method up the subclass hierarchy. if([super respondsToSelector:@selector(observeValueForKeyPath:ofObject:change:context:)]){ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } } - (void)dealloc { [self.view removeObserver:self forKeyPath:@"hidden"]; } // Here have the rest of your code for the search results table. @end 

Cela fonctionne dans tous les cas, y compris si le text est effacé.

Enfin, pour éviter que la table fasse un dégradé moche en gris puis en blanc lorsque la search est activée, utilisez ceci:

 self.searchController.dimsBackgroundDuringPresentation = NO; 

Swift 3 Version:

Si searchResultController n'est pas nul et que vous utilisez un controller tableau séparé pour afficher les résultats de la search, vous pouvez rendre ce controller de vue de table conforme à UISearchResultUpdating et dans la fonction updateSearchResults , vous pouvez simplement afficher la vue.

 func updateSearchResults(for searchController: UISearchController) { view.hidden = false } 

La version Swift 2.3 de l'approche de @ malhal:

 class SearchResultsViewController : UIViewController { var context = 0 override func viewDidLoad() { super.viewDidLoad() // Add observer view.addObserver(self, forKeyPath: "hidden", options: [ .New, .Old ], context: &context) } deinit { view.removeObserver(self, forKeyPath: "hidden") } override func observeValueForKeyPath(keyPath: Ssortingng?, ofObject object: AnyObject?, change: [Ssortingng : AnyObject]?, context: UnsafeMutablePointer<Void>) { if context == &self.context { if change?[NSKeyValueChangeNewKey] as? Bool == true { view.hidden = false } } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context) } } } 

Si vous ne souhaitez pas réduire les résultats, définissez la propriété dimsBackgroundDuringPresentation sur false .

Cela garantira que le contenu sous-jacent n'est pas estompé lors d'une search.

Vous devrez également vous assurer de renvoyer les résultats même lorsque searchText est vide, sinon une tablevue vide sera affichée.

Ce qui est caché est la vue du controller de résultats de search. Par conséquent, il suffit de le cacher chaque fois qu'il pourrait être caché. Faites simplement comme suit dans le controller de résultats de search:

 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.view.isHidden = false } func updateSearchResults(for searchController: UISearchController) { self.view.isHidden = false // ... your other code goes here ... } 

Maintenant, la vue des résultats (c'est-à-dire la vue de la table) est toujours visible, même lorsque le text de la barre de search est vide.

D'ailleurs, l'application iOS Mail se comporte comme ça, et je suppose que c'est ainsi qu'elle est implémentée (à less qu'Apple n'ait access à un paramètre secret privé UISearchController).

[Testé dans iOS 10 et iOS 11; Je n'ai testé sur aucun système antérieur.]

Je travaille récemment sur UISearchController. Je souhaite afficher l'historique des searchs dans searchResultsController lorsque la barre de search est vide. Ainsi searchResultsController doit apparaître lorsque UISearchController est présenté.

Je ne suis pas très satisfait des solutions qui returnnent le drapeau caché défini par UISearchController (comportement embedded). J'ai essayé une autre solution pour rendre le searchResultsController toujours visible en remplaçant la propriété cachée dans une vue personnalisée .

par exemple, mon searchResultsController est un UITableViewController. Je crée un VisibleTableView en tant que sous-class de UITableView, puis modifiez la class personnalisée UITableView de searchResultsController en VisibleTableView dans xib ou le storyboard. De cette façon, mon searchResultsController ne sera jamais caché par UISearchController.

Les bonnes choses ici:

  1. Plus facile à mettre en œuvre que KVO.

  2. Aucun timeout pour afficher searchResultsController. L'inversion de l'indicateur caché dans la méthode de délégation "updateSearchResults" fonctionne, mais il y a un timeout pour afficher searchResultsController.

  3. Il ne réinitialise pas le drapeau caché, donc il n'y a pas de trou d'interface user / saut entre caché et visible.

Swift 3 exemple de code :

 class VisibleTableView: UITableView { override var isHidden: Bool { get { return false } set { // ignoring any settings } } } 

Je pense que vous vous trompez.

SearchResultsController apparaît uniquement lorsqu'il y a des résultats. C'est légèrement différent de votre interprétation.

Les résultats sont chargés manuellement en fonction du text dans la barre de search. Vous pouvez donc l'intercepter si la barre de search est vide et renvoyer votre propre set de résultats.

J'ai passé beaucoup de time avec ceci, et finalement la solution que j'ai suivie est comme @ malhals, mais la quantité de code est considérablement réduite en utilisant le KVOController de facebook: https://github.com/facebook/KVOController . Un autre avantage est que si votre searchResultsController est un UINavigationController vous n'avez pas besoin de le sous-classr juste pour append le code de @ malhal.

 // always show searchResultsController, even if text is empty [self.KVOController observe:self.searchController.searchResultsController.view keyPath:@"hidden" options:NSKeyValueObservingOptionNew block:^(id observer, UIView* view, NSDictionary *change) { if ([change[NSKeyValueChangeNewKey] boolValue] == YES) { view.hidden = NO; } }]; self.searchController.dimsBackgroundDuringPresentation = NO; 

Le moyen le plus simple est d'utiliser ReactiveCocoa avec cette extension https://github.com/ColinEberhardt/ReactiveTwitterSearch/blob/master/ReactiveTwitterSearch/Util/UIKitExtensions.swift

  presentViewController(sc, animated: true, completion: { sc.searchResultsController?.view.rac_hidden.modify({ value -> Bool in return false }) } ) 

où sc est votre UISearchController

J'ai vraiment aimé la réponse de Simon Wang et j'ai travaillé avec et c'est ce que j'ai fait et cela fonctionne parfaitement:

Je sous-class UISearchController dans ma class personnalisée:

 class CustomClass: UISearchController { override var searchResultsController: UIViewController? { get { let viewController = super.searchResultsController viewController?.view.isHidden = false return viewController } set { // nothing } } } 

Assurez-vous également que vous ne l'avez pas dans votre code:

 self.resultsSearchController.isActive = true 

resultsSearchController est mon UISearchController