uitableviewcontroller raywenderlich bar ios ios6 uitableview uisearchdisplaycontroller

ios - raywenderlich - swift search bar programmatically



Fallo de aserciĆ³n al usar UISearchDisplayController en UITableViewController (7)

Cuando tuve este problema, la solución reemplazaba a tableView dequeueReusableCellWithIdentifier: @yourll con self.tableView

He intentado agregar funcionalidad simple de búsqueda a TableViewController en mi aplicación. Seguí el tutorial de Ray Wenderlich. Tengo un TableView con algunos datos, agregué la barra de búsqueda + controlador de visualización en el guión gráfico, y luego tengo este código:

#pragma mark - Table View - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BreedCell" forIndexPath:indexPath]; //Create PetBreed Object and return corresponding breed from corresponding array PetBreed *petBreed = nil; if(tableView == self.searchDisplayController.searchResultsTableView) petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row]; else petBreed = [_breedsArray objectAtIndex:indexPath.row]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; cell.textLabel.text = petBreed.name; return cell; } #pragma mark - Search -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString { [_filteredBreedsArray removeAllObjects]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",searchString]; _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy]; return YES; } -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption { // Tells the table data source to reload when scope bar selection changes [_filteredBreedsArray removeAllObjects]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name contains[c] %@",self.searchDisplayController.searchBar.text]; _filteredBreedsArray = [[_breedsArray filteredArrayUsingPredicate:predicate] mutableCopy]; return YES; }

Lo estándar, pero cuando ingreso texto en la barra de búsqueda se bloquea cada vez que aparece este error:

2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Assertion failure in -[UISearchResultsTableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460 2013-01-07 19:47:07.330 FindFeedo[3206:c07] *** Terminating app due to uncaught exception ''NSInternalInconsistencyException'', reason: ''unable to dequeue a cell with identifier BreedCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard''

Entiendo que en iOS 6 el sistema de manejo y delección de células cambió, y también que la búsqueda usa un TableView diferente, así que pensé que el problema era que la tabla de búsqueda con los resultados filtrados no conocía la celda, así que puse esto en mi viewDidLoad:

[self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"BreedCell"];

¡Y voilá! Funcionó ... Solo la primera vez que buscas. Si vuelve a los resultados originales y vuelve a buscar, la aplicación se bloquea con el mismo error. Pensé en agregar quizás todo el

if(!cell){//init cell here};

cosas al método cellForRow, pero eso no va en contra del propósito de tener el método dequeueReusableCellWithIdentifier: forIndexPath:? De todos modos, estoy perdido. ¿Qué me estoy perdiendo? Ayuda por favor. Gracias de antemano por todo su tiempo (:

Alex.


Dequeue la celda sin usar ''indexPath'' y en caso de que obtenga un elemento nulo, debe asignarlo manualmente.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"YourCellId"]; if (!cell) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"YourCellId"]; // fill your cell object with useful stuff :) return cell; }

Intentar utilizar self.tableView para dequeue la celda puede causar bloqueos cuando tiene una lista principal seccionada y una lista de búsqueda simple. Este código funciona en cualquier situación.


Después de buscar, ''tableView'' del método cellForRowAtIndexPath no parece una instancia de la tabla que usted defina. Entonces, puede usar una instancia de una tabla que defina la celda. En lugar de:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

Utilizar:

UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

(No use el método tableView of cellForRowAtIndexPath, use self.tableView ).


Estoy trabajando en ese tutorial también. El TableViewController predeterminado tiene "forIndexPath" y en su ejemplo no existe. Una vez que lo eliminé, la búsqueda funciona.

//Default code UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; //Replace with UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];


Intenta usar self.tableView en lugar de tableView en dequeueReusableCellWithIdentifier:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"BreedCell"]; //Create PetBreed Object and return corresponding breed from corresponding array PetBreed *petBreed = nil; if(tableView == self.searchDisplayController.searchResultsTableView) petBreed = [_filteredBreedsArray objectAtIndex:indexPath.row]; else petBreed = [_breedsArray objectAtIndex:indexPath.row]; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; cell.textLabel.text = petBreed.name; return cell; }

Este código funciona bastante bien

Nota

Si tiene celdas de altura personalizadas, no use

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

Use esto en su lugar

[self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];


La razón por la que funcionó muy bien en la primera ejecución pero luego se colgó si salió de la tabla de resultados y volvió para otra búsqueda es porque el Controlador de visualización de búsqueda está cargando una nueva UITableView cada vez que ingresa al modo de búsqueda.

En el modo de búsqueda, quiero decir, ha tocado el campo de texto y ha comenzado a escribir, en cuyo punto se genera una vista de tabla para mostrar los resultados, saliendo de este modo se logra presionando el botón de cancelar. Cuando toca el campo de texto por segunda vez y comienza a escribir de nuevo, está ingresando al "modo de búsqueda" por segunda vez.

Por lo tanto, para evitar el bloqueo, debe registrar la clase de celda para la vista de tabla para usar en searchDisplayController:didLoadSearchResultsTableView: delegue el método (desde UISearchDisplayDelegate ) en lugar de en el método viewDidLoad sus controladores.

Como sigue:

- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView { [tableView registerClass:[DPContentTableCell class] forCellReuseIdentifier:cellIdentifier]; [tableView registerClass:[DPEmptyContentTableCell class] forCellReuseIdentifier:emptyCellIdentifier]; }

Esto me tomó por sorpresa porque en iOS 7 ... la vista de tabla se está reutilizando. Entonces puede registrar la clase en viewDidLoad si lo prefiere. Por el legado heredado, mantendré mi registro en el método delegado que mencioné.


para swift 3 solo necesitas agregar uno mismo:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = self.tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! YourCell ... }