UISearchDisplayController: cómo cargar previamente searchResultTableView

Quiero mostrar algunos contenidos pnetworkingeterminados cuando el usuario toca la barra de búsqueda, pero antes de ingresar cualquier text.

Tengo una solución trabajando con settext:

- (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [searchDisplayController.searchBar setText:@" "]; } 

Esto funciona, pero no es elegante y desaparece el text sugerido en la barra de búsqueda.

¿Hay una manera mejor de precargar datos en SearchResultTableView en un UISearchDisplayController, sin tener que implementar toda la funcionalidad de UISearch usted mismo en un controller personalizado?

Para ver una demostración del efecto deseado, mire el cuadro de búsqueda de Safari, si lo toca, la interfaz de búsqueda se abre con las búsquedas anteriores mostradas.

Bien, lo tengo. Precargue su dataSource con algunos datos y realice el siguiente pirateo (nada ilegal) y obtendrá la tablaView para mostrar. Tenga en count que puede haber algo de limpieza que hacer, pero esto hará que se muestren sus datos pnetworkingeterminados.

En viewDidLoad del controller de vista de lo que posee el UISearchBar:

 [super viewDidLoad]; [self.searchDisplayController.searchResultsTableView reloadData]; // whatever you named your search bar - mine is property named searchBar CGRect testFrame = CGRectMake(0, 20, self.searchBar.frame.size.width, 100); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.searchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; 

Esto es lo que está sucediendo:
UISearchBar no quiere mostrar searchResultsTableView hasta que comience a editar. Si tocas el tableView (por ejemplo, reloadData) se cargará y estará allí, sentado en la memory con frame = CGRectZero. Le da un marco adecuado y luego lo agrega a la vista superior de la búsqueda Bar, et voila.

Verifiqué que esto es correcto al mostrar la vista de supervisión de la barra de búsqueda y la vista de supervisión de la tableView después de una carga adecuada de tableView: tienen la misma supervisión. Entonces, vuelvo y agrego el tableView a la supervista temprano, y ciertamente aparece. Para mí, apareció atenuado (tal vez otra vista por encima de él? Alpha set lower?), Pero todavía se podía hacer clic. No fui más lejos, pero definitivamente te muestra tu tablaView sin ninguna interacción del usuario.

Disfrutar,

Damien

Encontré una solución mucho mejor a este problema, y ​​parece funcionar perfectamente en iOS 6 y 7. Si bien todavía es un hack, es un hack mucho más limpio y seguro que el anterior. ¡Las otras soluciones no funcionan de forma coherente y evitan que algunos methods UISearchDisplayDelegate se disparen alguna vez! Además, tuve complejos problemas de inserción que no pude resolver con los methods anteriores. El problema principal con las otras soluciones es que confunden seriamente los elementos internos del UISearchDisplayController. Mi solución se basa en la observación de que UISearchDisplayContoller es un UISearchbarDelegate y que la tabla de ondulación automática y visualización de resultados se puede activar simulando una pulsación de teclas en el campo de búsqueda. Asi que:

 - (void) searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { if ([controller respondsToSelector: @selector(searchBar:textDidChange:)]) [(id<UISearchBarDelegate>)controller searchBar: controller.searchBar textDidChange: @" "]; } 

Este código es una testing futura contra fallas comprobando que responde al método UISearchbarDelegate y envía espacio @ "" para engañar al UISearchDisplayController en el pensamiento del usuario ha escrito una letra.

Ahora, si el usuario escribe algo y luego lo borra, la tabla se volverá a atenuar. Las otras soluciones tratan de solucionarlo haciendo algo en el método searchDisplayController: didHideSearchResultsTableView: method. Pero esto no tiene sentido para mí, ya que seguramente cuando cancele la búsqueda deberá ocultar la tabla de resultados y es posible que deba ejecutar el código en este caso. Mi solución para esta parte es la subclass (obsérvese que probablemente podría utilizar una categoría Swizzled de método para que funcione en todas partes si es necesario en su proyecto):

 // privately declare protocol to suppress compiler warning @interface UISearchDisplayController (Super) <UISearchBarDelegate> @end // subclass to change behavior @interface GMSearchDisplayController : UISearchDisplayController @end @implementation GMSearchDisplayController - (void) searchBar: (UISearchBar *) searchBar textDidChange: (NSString *) searchString { if (searchString.length == 0) searchString = @" "; if ([super respondsToSelector: @selector(searchBar:textDidChange:)]) [super searchBar: searchBar textDidChange: searchString]; } @end 

Este código funciona interceptando el método de delegado textDidChange y cambiando las cadenas nil o vacías a la cadena espacial @ "" previniendo la ocultación / regulación normal que ocurre en una barra de búsqueda vacía. Si está utilizando este segundo bit de código, entonces podría modificar el primer bit para pasar un cero en vez de @ "", ya que este segundo bit hará la conversión necesaria a @ "" para usted.

En mi propio proyecto, necesitaba manejar el caso de que el usuario escriba un espacio, por lo que en lugar de usar "@" arriba un token definido:

 // arbitrary token used internally #define SEARCH_PRELOAD_CONDITIONAL @"_#preresults#_" 

Y luego manejarlo internamente al convertirlo de nuevo en nil cadena:

 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { if ([searchString isEqualToString: SEARCH_PRELOAD_CONDITIONAL]) searchString = nil; } 

¡Disfrutar! 🙂

Solución de trabajo para iOS 7:

 // When the tableView is hidden, put it back - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { [self.searchDisplayController.searchResultsTableView reloadData]; controller.searchResultsTableView.hidden = NO; // Also, remove the dark overlay for (UIView *v in [[controller.searchResultsTableView superview] subviews]) { // This is somewhat hacky.. if (v.alpha < 1) { [v setHidden:YES]; } } } -(void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { [self.searchDisplayController.searchResultsTableView reloadData]; if (self.searchDisplayController.active == YES) { tableView.hidden = NO; } } 

Tengo la solucion Inserte estos tres methods. Debe tener la vista de tabla precargada con los datos para que esto funcione. Tengo estos códigos funcionando en mi código, por lo que tiene que funcionar para usted siempre que haya cargado previamente los datos y esté utilizando el controller de visualización de búsqueda.

 - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { CGRect testFrame = CGRectMake(0, self.notesSearchBar.frame.size.height, self.notesSearchBar.frame.size.width, self.view.frame.size.height - self.notesSearchBar.frame.size.height); self.searchDisplayController.searchResultsTableView.frame = testFrame; [self.notesSearchBar.superview addSubview:self.searchDisplayController.searchResultsTableView]; // [self.view addSubview:self.searchDisplayController.searchResultsTableView]; controller.searchResultsTableView.hidden = NO; } -(void) searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller { controller.searchResultsTableView.hidden = YES; } 

Esto funciona en iOS 8:

 - (void)searchDisplayController:(UISearchDisplayController *)controller didHideSearchResultsTableView:(UITableView *)tableView { self.searchDisplayController.searchResultsTableView.hidden = NO; } - (void)searchDisplayControllerDidBeginSearch:(UISearchDisplayController *)controller { self.searchDisplayController.searchResultsTableView.hidden = NO; [self.searchDisplayController.searchResultsTableView.superview.superview bringSubviewToFront:self.searchDisplayController.searchResultsTableView.superview]; CGRect frame = self.searchDisplayController.searchResultsTableView.frame; self.searchDisplayController.searchResultsTableView.frame = CGRectMake(frame.origin.x, 64, frame.size.width, frame.size.height); } 

Sin embargo, no me gustó este hack y reemplazé el searchDisplayController por mi propia implementación (UISearchBar con UITableView).

Probé lo siguiente en iOS 9 con UISearchController.

De forma pnetworkingeterminada, cuando no hay text en UISearchBar, la tabla que se muestra será su vista de tabla original (referida como originalTableView de aquí en adelante). Esto puede o no tener una capa dimsBackgroundDuringPresentation dependiendo del valor de dimsBackgroundDuringPresentation .

Una vez que el usuario ingrese cualquier text en el UISearchBar, se mostrará el contenido de la nueva vista de tabla (me referiré a esto como searchTableView ).

Tenga en count que en estas dos soluciones, estoy implementando el UISearchController de manera similar a como lo hace Apple en este ejemplo ; a saber, hay dos UITableViewController separados a cargo de mostrar los datos.

Solución 1: implementación complicada, animation más suave

Para una animation más suave:

  1. Implemente los methods willPresentSearchController y WillDismissSearchController de UISearchControllerDelegate.
  2. En willPresent, actualice los datos de su originalTableView para estar listo para mostrar cualquier dato de text cero que desee, luego llame a reloadData() .
  3. En willDismiss, revertir el process para mostrar los contenidos originales y llamar a reloadData() .

Ejemplo:

 // here tableView refers to originalTableView extension ViewController: UISearchControllerDelegate { func willPresentSearchController(searchController: UISearchController) { data = ["A", "B", "C"] tableView.reloadData() } func willDismissSearchController(searchController: UISearchController) { data = ["a", "b", "c"] tableView.reloadData() } } 

En este ejemplo ficticio, los datos se muestran como a,b,c cuando el usuario no está enfocado en UISearchBar, pero se muestra como A,B,C una vez que el usuario toca el UISearchBar.

Solución 2: Rápida para implementar, animation picada

En lugar de implementar la lógica para el controller de búsqueda en both originalTableView y searchTableView, puede usar esta solución para simplemente mostrar el searchTableView aunque esté oculto de forma pnetworkingeterminada.

Lo más probable es que ya esté implementando el protocolo UISearchResultsUpdating. Simplemente llamando a tableView.hidden = false en ese método, debe get el comportamiento que tableView.hidden = false ; aunque con una animation less que estelar.

 // here tableView refers to searchTableView extension SearchViewController: UISearchResultsUpdating { func updateSearchResultsForSearchController(searchController: UISearchController) { tableView.hidden = false filterData(text: searchController.searchBar.text!) tableView.reloadData() } } 

¿Por qué no echas un vistazo al proyecto TableSearch que viene en Xcode? Dirige más o less lo que necesita. Muestra una tabla al principio y la difumina cuando se toca el campo de búsqueda. Consulte TableSearch en Documentation y API reference en Xcode 4 bajo ayuda.

También eche un vistazo a esto. Casi hace lo que necesita con un UISearchBar y una UITableView. Prefiero ese enfoque en su lugar. Ajustarla

Y para abordar más sus necesidades, sugeriría usar dos fonts de datos. Uno con todos los contenidos (esto es lo que mostrarías al principio) y uno para contener los resultados de búsqueda filtrados. Ahora avance y vacíe la primera fuente de datos y llénela con el contenido de la segunda para almacenar y mostrar débilmente los resultados de la búsqueda anterior. Proceda de esta manera. Use este enfoque en el código de TableSearch para su tarea.

Aquí hay una manera de rellenar previamente el searchController.

// 1. Guardar resultados de búsqueda anteriores tan pronto como el usuario ingrese el text

 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { // save searchString return YES; } 

// 2. carga la cadena de búsqueda anterior al inicio

 - (void)viewDidLoad { // create data source for table view // searchData may be a NSMutableArray property defined in your interface self.searchData = // search your master list for searchString // or create your own list using any search criteria you want // or you may act depending on user preference if(!showPreviousSearch) { // [searchData removeAllObjects]; } } 

// 3. proporcione la fuente de datos correcta cuando se le solicite

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { ... } NSMutableArray *dataSource = nil; if (tableView == [[self searchDisplayController] searchResultsTableView]) { dataSource = self.searchData; } else { dataSource = self.masterData; } ... return cell; } 

// Espero que esto ayude.

Gracias