UISearchBar desaparece de tableHeaderView al usar beginUpdates / endUpdates

Tengo un controller de vista de tabla con un UISearchController que establece UISearchBar como tableView.tableHeaderView . Al actualizar los resultados de búsqueda, utilizo los beginUpdates y endUpdates y los methods relacionados para actualizar los datos para la vista de tabla.

Esto hace que la barra de búsqueda desaparezca; the tableHeaderView se establece en una UIView genérica UIView del mismo tamaño que la barra de búsqueda. Si simplemente uso reloadData lugar de todo el procedimiento beginUpdates / endUpdates , todo está bien.

El controller de vista de tabla está embedded en un controller de vista normal; no hay ningún controller de navigation involucrado. Esta es la implementación completa del controller de vista de tabla necesario para reproducir el problema:

 - (void)viewDidLoad { [super viewDidLoad]; self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; self.searchController.searchResultsUpdater = self; self.searchController.dimsBackgroundDuringPresentation = NO; self.tableView.tableHeaderView = self.searchController.searchBar; } - (void)updateSearchResultsForSearchController:(UISearchController *)searchController { [self.tableView beginUpdates]; [self.tableView endUpdates]; } 

¿Por qué esto hace que la barra de búsqueda se reemplace con una vista en blanco y cómo se puede evitar?

Cuando primero hace clic en UISearchController's UISearchController, toma aproximadamente 0.5s para que searchBar se anime. Pero el método delegado llamó self.tableView.endUpdates() , la animation se interrumpió.
La barra de búsqueda se ha quedado atascada en el medio de la animation, y no puede ver su interfaz de usuario:
introduzca la descripción de la imagen aquí

Una solución alternativa es verificar si searchBar está en animation y retrasar self.tableView.endUpdates() cuando está dentro.

 func updateSearchResultsForSearchController(searchController: UISearchController){ self.tableView.beginUpdates() //Do some updates if !searchController.searchBar.showsCancelButton{ self.tableView.performSelector(#selector(UITableView.endUpdates), withObject: nil, afterDelay: 1) }else{ self.tableView.endUpdates() } } 

Pequeña revisión sobre beginUpdates, endUpdates and reloadData

beginUpdates:: inicia una serie de llamadas a methods que insertan, eliminan o seleccionan filas y secciones de la vista de tabla. Llame a este método si desea que las operaciones posteriores de inserción, eliminación y selección (por ejemplo, cellForRowAtIndexPath: y indexPathsForVisibleRows) se animen simultáneamente. También puede usar este método seguido del método endUpdates para animar el cambio en las alturas de las filas sin volver a cargar la celda. Este grupo de methods debe concluir con una invocación de endUpdates. Estos pares de methods pueden anidarse. Si no realiza las llamadas de inserción, eliminación y selección dentro de este bloque, los attributes de la tabla como el recuento de filas pueden volverse inválidos. No debe llamar a reloadData dentro del grupo; si llama a este método dentro del grupo, debe realizar las animaciones usted mismo.

endUpdates: concluye una serie de llamadas a methods que insertan, eliminan, seleccionan o vuelven a cargar filas y secciones de la vista de tabla. Llamas a este método para agrupar una serie de llamadas a methods que comienzan con beginUpdates y que consiste en operaciones para insert, eliminar, seleccionar y volver a cargar filas y secciones de la vista de tabla. Cuando llama a endUpdates, UITableView anima las operaciones de forma simultánea. Las invocaciones de beginUpdates y endUpdates pueden anidarse. Si no realiza las llamadas de inserción, eliminación y selección dentro de este bloque, los attributes de la tabla como el recuento de filas pueden volverse inválidos.

reloadData: vuelve a cargar las filas y secciones de la vista de tabla. Llame a este método para volver a cargar todos los datos que se utilizan para build la tabla, incluidas las celdas, los encabezados de sección y los pies de página, las matrices de índices, etc. Para la eficiencia, la vista de tabla vuelve a mostrar solo aquellas filas que son visibles. Ajusta los desplazamientos si la tabla se contrae como resultado de la recarga. El delegado o fuente de datos de la vista de tabla llama a este método cuando quiere que la vista de tabla recargue por completo sus datos. No debe invocarse en los methods que insertan o eliminan filas, especialmente dentro de un bloque de animation implementado con llamadas a beginUpdates y endUpdates.

Ahora en el caso de la búsqueda no sabemos qué filas van a afectar también cada vez que los resultados del resultado de búsqueda sean diferentes, creo que uno no debería usar

 [self.tableView beginUpdates]; [self.tableView endUpdates]; 

como se usa cuando está realizando la insert, update or delete operación en tableview y conoce su indexPath .

Mejor uso [self.tableView reloadData]; ya que solo actualizará las filas visibles o la sección en tableview. También consulte el código de ejemplo de Apple para la búsqueda de tablas con UISearchController , también recomienda utilizar reloadData .

Haga los cambios respectivos y está listo para hacerlo.

Codificación feliz 🙂