tutorial searchcontroller bar ios iphone ios8 uisearchcontroller

ios - searchcontroller - uisearchbar swift 4



UISearchController: muestra resultados incluso cuando la barra de búsqueda está vacía (14)

Con cosas complicadas como esta, recomiendo el enfoque de martillo. Eso es detectar cuándo algo intenta ocultarlo y cuándo lo hace, cambiarlo de nuevo. Esto se puede hacer a través de KVO (Key Value Observing). Esto funcionará sin importar qué, sin tener que manejar todas las complejidades de la barra de búsqueda. Lo siento, el código es complicado pero KVO es una API de estilo anterior, pero mi código sigue la práctica recomendada. En su SearchResultsViewController ponga esto:

static int kHidden; @implementation SearchResultsViewController -(void)viewDidLoad{ [super viewDidLoad]; [self.view addObserver:self forKeyPath:@"hidden" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:&kHidden]; } - (void)observeValueForKeyPath:(NSString *)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

Esto funciona en todos los casos, incluso si el texto se borra.

Por último, para evitar que la mesa haga un desvanecimiento feo a gris y luego a blanco cuando se active la búsqueda, usa esto:

self.searchController.dimsBackgroundDuringPresentation = NO;

Según tengo entendido, el comportamiento predeterminado de UISearchController es:

  1. Al tocar la barra de búsqueda, el fondo se atenúa y se muestra el botón ''cancelar''. SearchResultsController no se muestra hasta este punto.
  2. SearchResultsController solo se muestra si la barra de búsqueda no está vacía.

Quiero mostrar SearchResultsController incluso cuando la barra de búsqueda está vacía pero seleccionada (es decir, el caso 1 de arriba).

En pocas palabras, en lugar de la atenuación del fondo, me gustaría mostrar los resultados de la búsqueda.

¿Hay una manera de hacer esto?

Más aclaraciones:

No estoy usando UISearchController para filtrar los resultados mostrados en la vista en la que se muestra, sino otros resultados no relacionados. Será como lo que hace Facebook en su ''News Feed''. Al tocar la barra de búsqueda, se muestran las sugerencias de búsqueda inicialmente y luego, cuando comenzamos a editar, muestra los resultados de búsqueda que pueden no estar relacionados con las noticias.


Creo que estás equivocado.

SearchResultsController solo aparece cuando hay resultados. Esto es ligeramente diferente a su interpretación.

Los resultados se cargan manualmente según el texto en la barra de búsqueda. Por lo tanto, puede interceptarlo si la barra de búsqueda está vacía y devolver su propio conjunto de resultados.


He intentado la solución de PetahChristian, el resultado de la precarga se mostró cuando enfocamos la barra de búsqueda por primera vez, pero cuando ingresamos algo y luego lo borramos, los resultados de la precarga no volverán a aparecer.

Se me ocurrió otra solución. Solo necesitamos agregar un delegado en SearchResultsController y llamarlo cuando nuestro searchController.searchBar.text está vacío. Algo como esto:

SearchResultsController:

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

Y en el controlador que contiene SearchController, agregamos nuestro delegado:

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



La versión Swift 2.3 del enfoque 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: String?, ofObject object: AnyObject?, change: [String : 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) } } }


Lo que se oculta es la vista del controlador de resultados de búsqueda. Por lo tanto, es suficiente para mostrarlo en cualquier momento que pueda estar oculto. Simplemente haga lo siguiente en el controlador de resultados de búsqueda:

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 ... }

Ahora la vista de resultados (es decir, la vista de tabla) siempre está visible, incluso cuando el texto de la barra de búsqueda está vacío.

Por cierto, la aplicación de correo de iOS se comporta de esta manera, y asumo que así es como se implementa (a menos que Apple tenga acceso a alguna configuración privada secreta de UISearchController).

[Probado en iOS 10 y iOS 11; No probé en ningún sistema anterior.]


Pasé mucho tiempo con esto, y en última instancia, la solución que encontré es como la de @ malhals, pero la cantidad de código se reduce significativamente al usar KVOController de Facebook: https://github.com/facebook/KVOController . Otra ventaja aquí es que si su searchResultsController es un UINavigationController entonces no necesita subclasificarlo solo para agregar el código 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;


Realmente me gustó la respuesta de Simon Wang y trabajé con ella y esto es lo que hice y funciona perfectamente:

Subclasifico el UISearchController en mi clase personalizada:

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

También asegúrate de no tener esto en tu código:

self.resultsSearchController.isActive = true

resultadosSearchController es mi UISearchController


Recientemente estoy trabajando en UISearchController. Quiero mostrar el historial de búsqueda en searchResultsController cuando la barra de búsqueda está vacía. Por lo tanto, searchResultsController debe aparecer cuando se presenta UISearchController.

No estoy del todo satisfecho con las soluciones que activan el indicador oculto establecido por UISearchController (comportamiento incorporado). He intentado otra solución para hacer que searchResultsController siempre esté visible al invalidar la propiedad oculta en una vista personalizada .

por ejemplo, mi searchResultsController es un UITableViewController. Creo un VisibleTableView como una subclase de UITableView, y luego cambio la clase personalizada UITableView de searchResultsController a VisibleTableView en xib o storyboard. De esta manera, mi searchResultsController nunca será ocultado por UISearchController.

Las cosas buenas aquí:

  1. Más fácil de implementar que KVO.

  2. Sin demora para mostrar searchResultsController. Activar el indicador oculto en el método delegado "updateSearchResults" funciona, pero hay un retraso para mostrar el searchResultsController.

  3. No restablece la bandera oculta, por lo que no hay un intervalo UI / salto entre lo oculto y lo visible.

Código de muestra Swift 3 :

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


Si no desea atenuar los resultados, establezca la propiedad dimsBackgroundDuringPresentation en false .

Esto asegurará que el contenido subyacente no se vea atenuado durante una búsqueda.

También deberá asegurarse de devolver los resultados incluso cuando el searchText esté vacío, de lo contrario se mostrará una vista de tabla vacía.


Si su barra de búsqueda está activa pero no tiene texto, se muestran los resultados de la vista de tabla subyacente. Ese es el comportamiento incorporado, y la razón por la cual searchResultsController está oculto para ese estado.

Para cambiar el comportamiento cuando la búsqueda está activa pero no se está filtrando, tendrá que mostrar searchResultsController cuando normalmente todavía está oculto.

Puede haber una buena manera de lograr esto a través de <UISearchResultsUpdating> y updateSearchResultsForSearchController: Si puedes resolverlo a través del protocolo, esa es la forma preferida de hacerlo.

Si eso no ayuda, te quedas con hackear el comportamiento incorporado. No lo recomendaría ni confiaría en él, y será frágil, pero aquí hay una respuesta si elige esa opción:

  1. Asegúrese de que su tableViewController se ajuste a <UISearchControllerDelegate> y agregue

    self.searchController.delegate = self;

  2. Implementar willPresentSearchController:

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

    Esto hace que el searchResultsController visible después de que su UISearchController establezca en oculto.

  3. Implementar didPresentSearchController:

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

Para una mejor manera de evitar el comportamiento incorporado, vea la respuesta de malhal .


Simplemente puede implementar el protocolo UISearchResultsUpdating y configurar la vista del controlador de resultados para que siempre se muestre en updateSearchResultsForSearchController :

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

Esto funciona porque el método se llama incluso cuando la barra de búsqueda está activada, sin ningún texto.


Swift 4 versión de malhals responde :

class SearchController: UISearchController { private var viewIsHiddenObserver: NSKeyValueObservation? override func viewDidLoad() { super.viewDidLoad() viewIsHiddenObserver = self.searchResultsController?.view.observe(/.hidden, changeHandler: { [weak self] (view, _) in guard let searchController = self else {return} if view.isHidden && searchController.searchBar.isFirstResponder { view.isHidden = false } }) } }

Tenga en cuenta el [weak self] . De lo contrario, introducirías un ciclo de retención.


Versión Swift 3:

Si su searchResultController no es nulo y está usando un controlador de vista de tabla separado para mostrar los resultados de búsqueda, entonces puede hacer que ese controlador de vista de tabla se ajuste a UISearchResultUpdating y en la función updateSearchResults , simplemente puede mostrar la vista.

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

Versión Swift 4:

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