Error de aserción cuando se utiliza UISearchDisplayController en UITableViewController

He estado tratando de agregar simple funcionalidad de Búsqueda de un TableViewController en mi aplicación. He seguido Ray Wenderlich del tutorial. Tengo un formato tableview con algunos datos, he añadido la barra de búsqueda + controlador de pantalla en el guión, 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;
    }

El estándar de cosas, pero cuando yo escriba el texto en la barra de búsqueda que se bloquea a cada rato con 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, la manipulación y sacarlo de la cola del sistema para las células cambiado, y también que la búsqueda utiliza un diferente formato tableview, así que pensé que el problema era que la búsqueda en formato tableview con los resultados filtrados no sabía acerca de la célula, así que me puse esto en mi viewDidLoad:

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

Y voila! Funcionó… Sólo la primera vez que usted busca. Si se va a volver a los resultados originales y volver a buscar, la aplicación se bloquea con el mismo error. Pensé que tal vez la adición de todos los

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

cosas a la cellForRow método, pero no se de que va en contra de toda propósito de tener la dequeueReusableCellWithIdentifier:forIndexPath: método? De todos modos, estoy perdido. Lo que me estoy perdiendo? Ayuda, por favor. Gracias de antemano por todo tu tiempo (:

Alex.

InformationsquelleAutor acib708 | 2013-01-08

7 Kommentare

  1. 193

    Trate de usar el auto.formato tableview en lugar de en formato 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 ha personalizado la altura de las células, no utilice

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

    Usar este en lugar

    [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    • Funciona muy bien!, Gracias!
    • no se que acaba de crear instancias de nuevas células a partir de una tabla a otra de forma indefinida? si la cola de las celdas de una tabla y dándoles a otro suena como una mala idea
    • no, esto está bien. Pero si quieres ver las diferentes celdas de la tabla principal y la tabla de búsqueda, puede utilizar diferentes cellIdentifiers para prototipos diferentes de células en el Storyboard
    • Pensé que esto iba a funcionar también. No. En mi caso, tratando de eliminar de la cola de la celda de mi tabla principal de la tabla de Búsqueda que a veces causa un accidente.
    • Funciona como un encanto! Tira de las células de corregir PUNTA en el guión gráfico. Por supuesto, esto conduce a la pregunta: «¿qué pasa si quiero usar los diferentes células en la búsqueda de controlador de la vista de la mesa?»
    • No funciona. Intente la búsqueda, a continuación, cancelar (salida de la superposición de los resultados de modo) y, a continuación, volver a buscar. Se bloquea.
    • He encontrado la solución correcta, a ver mi respuesta. stackoverflow.com/a/18228417/662605
    • La propuesta de solución todavía plantea una excepción para mí. Sin embargo, parece que funciona como se espera si puedo reemplazar dequeueReusableCellWithIdentifier:forIndexPath: por dequeueReusableCellWithIdentifier:.
    • gracias! auto.formato tableview en lugar de en formato tableview era el problema! protector de la vida!
    • El código plantea una «solicitud de rect a invalid index» ruta de excepción cuando se solicita una indexPath que no está presente en self.tableView. En la mayoría de los casos (cuando el filtrado de la norma en formato tableview) esto no es un problema debido a que el conjunto de búsqueda indexPaths es un subconjunto estricto de la norma establecida de indexPaths. Sin embargo, es algo para tener en cuenta! Por ejemplo, usted no puede utilizar las secciones en la norma y a omitir en los resultados de búsqueda en formato tableview. Por desgracia, esto es – a pesar de ser feo como @figha señaló – la única solución que conozco que trabaja con Guión gráfico dinámico prototipo de las células.
    • Añadir a mi comentario anterior: por supuesto, esto es un bug en iOS. He iniciado la openradar.me/16252999 si desea engañar a los de ella.
    • Creo que no me hubiera imaginado alguna vez que a uno mismo.
    • MUCHAS GRACIAS! 😀
    • Estoy experimentando problemas con esta propuesta de solución, donde la búsqueda de la vista de tabla comparte el reutilizar las células con el original de la vista de tabla. UIKit (iOS 7.1) puede registrar mensajes de advertencia «no hay ningún índice de ruta para la celda de tabla que se va a reutilizar». Más tarde, se puede bloquearse hacer para el acceso no válido indexPaths. Parece que la búsqueda de la vista de tabla debe utilizar sus propias células de la caché. Sin embargo, esto puede requerir para configurar manualmente segues y otras cosas asociadas a esta nuevas células, que por otro lado ya el programa de instalación en las células asociadas a la tabla original vista en un storyboard.
    • Creo que no es segura la utilización de self.tableView dentro de cellForRowAtIndexPath: método si tiene searchDisplayController. Mejor utilizar sólo tableView yo.e el argumento.
    • He estado buscando izquierda y la derecha para la solución a esto – con la mayoría de la gente lo que sugiere soluciones que significaba prototipo de células que se generan en el Guión no iba a funcionar. Y después de todo eso … eso es todo. self. que hizo por mí. Gracias. Gracias.

  2. 14

    La razón por la que funcionó muy bien en la primera carrera, pero luego se estrelló si usted sale de la tabla de resultados y fue de nuevo para otra búsqueda es porque, en la Búsqueda de Controlador de Pantalla es la carga de una nueva UITableView cada vez que entras en el modo de búsqueda.

    Por el modo de búsqueda es decir, han aprovechado el campo de texto y has comenzó a escribir, en la que el punto de vista de la tabla se genera para mostrar los resultados, salir de este modo se consigue pulsando el botón cancelar. Cuando usted presiona el campo de texto en el segundo tiempo y empezar a escribir de nuevo, este es entrar en «modo de búsqueda» para el segundo tiempo.

    Por lo que para evitar el bloqueo se debe registrar la clase de células de la vista de tabla para su uso en la searchDisplayController:didLoadSearchResultsTableView: método de delegado (a partir de UISearchDisplayDelegate) de en lugar de en sus controladores viewDidLoad método.

    De la siguiente manera:

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

    Este me cogió por sorpresa, ya que en iOS 7… la vista de la tabla se reutilizan. Así que usted puede registrar la clase en viewDidLoad si usted prefiere. Para el legado de vosotros, voy a mantener mi inscripción en el método delegado he mencionado.

    • Lamentablemente esto no funciona con Guión gráfico dinámico prototipo de las células.
    • Pero funciona muy bien con las células registradas por la punta. Buena solución.
  3. 12

    Después de buscar, ‘formato tableview’ de cellForRowAtIndexPath método no parece un ejemplo de la Tabla que usted defina. Así, usted puede utilizar una instancia de una tabla que define la celda. En lugar de:

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

    Uso:

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

    (No utilice el formato tableview de cellForRowAtIndexPath método, el uso de auto.formato tableview.)

    • +1. Se necesita auto.formato tableview en mi swift aplicación de este concepto.
  4. 3

    De la cola el móvil sin usar el ‘indexPath y en caso de obtener un nil elemento, usted tiene que asignar 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;
    }

    Tratando de usar el auto.formato tableview para quitar de la cola de la célula puede causar accidentes cuando usted tiene un seccionada lista principal y una simple lista de búsqueda.
    Este código en su lugar de trabajo en cualquier situación.

    • Esto no funciona si tu celular es costumbre en el Guión gráfico y debe ser instanciado a partir de ella y no de su clase.
  5. 3

    Cuando he tenido este problema, la solución fue reemplazar tableView dequeueReusableCellWithIdentifier:@yourcell con self.tableView

  6. 2

    Estoy trabajando en el tutorial también. El valor predeterminado TableViewController ha «forIndexPath» y en su ejemplo no existe. Una vez que se retira la búsqueda de obras.

    //Default code
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    //Replace with
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    • Lamentablemente esto no funciona con Guión gráfico dinámico prototipo de las células.
  7. 2

    para swift 3 sólo se necesita añadir de auto:

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

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea