Error de aserción en dequeueReusableCellWithIdentifier: forIndexPath:


324

Así que estaba haciendo un lector de rss para mi escuela y terminé el código. Ejecuté la prueba y me dio ese error. Aquí está el código al que se refiere:

- (UITableViewCell *)tableView:(UITableView *)tableView 
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = 
     [tableView dequeueReusableCellWithIdentifier:CellIdentifier 
                                     forIndexPath:indexPath];
    if (cell == nil) {

        cell = 
         [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle  
                                reuseIdentifier:CellIdentifier];

    }

Aquí está el error en la salida:

2012-10-04 20: 13: 05.356 Reader [4390: c07] * Error de aserción en - [UITableView dequeueReusableCellWithIdentifier: forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460 2012-10-04 20: 13: 05.357 Reader [4390: c07] * Finalización de la aplicación debido a la excepción no detectada 'NSInternalInconsistencyException', razón: 'no se puede retirar una celda con identificador Cell - debe registrar una punta o una clase para el identificador o conectar una celda prototipo en un guión gráfico ' * Primera pila de llamadas tiro: (0x1c91012 0x10cee7e 0x1c90e78 0xb64f35 0xc7d14 0x39ff 0xd0f4b 0xd101f 0xb980b 0xca19b 0x6692d 0x10e26b0 0x228dfc0 0x228233c 0x228deaf 0x1058cd 0x4e1a6 0x4ccbf 0x4cbd9 0x4be34 0x4bc6e 0x4ca29 0x4f922 0xf9fec 0x46bc4 0x47311 0x2cf3 0x137b7 0x13da7 0x14fab 0x26315 0x2724b 0x18cf8 0x1becdf9 0x1becad0 0x1c06bf5 0x1c06962 0x1c37bb6 0x1c36f44 0x1c36e1b 0x147da 0x1665c 0x2a02 0x2935 ) libc ++ abi.dylib: terminar llamado lanzando una excepción

y aquí está el código que muestra en la pantalla de error:

int main(int argc, char *argv[])
{
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

¡por favor ayuda!


posible duplicado de falla
Venk

Respuestas:


488

Estás usando el dequeueReusableCellWithIdentifier:forIndexPath:método. La documentación para ese método dice esto:

Importante: debe registrar un archivo de clase o plumín utilizando el método registerNib:forCellReuseIdentifier:o registerClass:forCellReuseIdentifier:antes de llamar a este método.

No registró una punta o una clase para el identificador de reutilización "Cell".

Al mirar su código, parece esperar que regrese el método de eliminación de cola nilsi no tiene una celda que le proporcione. Necesita usar el dequeueReusableCellWithIdentifier:para ese comportamiento:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Tenga en cuenta que dequeueReusableCellWithIdentifier:y dequeueReusableCellWithIdentifier:forIndexPath:son diferentes métodos. Ver doc para el primero y el segundo .

Si desea comprender por qué querría usar alguna vez dequeueReusableCellWithIdentifier:forIndexPath:, consulte estas preguntas y respuestas .


166
DIOS MIO. ¿Por qué la plantilla predeterminada de Xcode para un UITableViewController le proporciona automáticamente dequeueReusableCellWithIdentifier: forIndexPath :? Tan inútil.
spstanley

15
El dequeueReusableCellWithIdentifer:forIndexPath:(introducido en iOS6) es una buena mejora, ya que no necesita verificar si la celda es nula. (Entonces UITableViewControllerfunciona de manera similar a UICollectionView) Pero sí, es molesto que este cambio no sea un comentario en la plantilla y que el mensaje de aserción / bloqueo no sea más útil.
Jason Moore

2
Por lo menos, pensaría que sería por defecto UITableViewCell en lugar de implosionar. Baka
BadPirate

13
La última línea de esta respuesta es dorada: he sido mordido más de una vez al usar dequeueReusableCellWithIdentifier:forIndexPath:cuando debería haber estado usando dequeueReusableCellWithIdentifier:.
ele

Esta respuesta es perfecta. Tengo una pregunta: tengo un tableViewController como mi controlador de vista inicial. En didSelectRow ... Estoy empujando otra tableViewController en la pila de navegación. ¿Cómo es que solo tengo que registrar una celda para la segunda tableViewController, no la inicial?
ArielSD

137

Creo que este error se trata de registrar su punta o clase para el identificador.

Para que pueda mantener lo que está haciendo en su función tableView: cellForRowAtIndexPath y simplemente agregue el código a continuación en su viewDidLoad:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Me ha funcionado. Espero que pueda ayudar.


3
Un pequeño inconveniente con esto: asegúrese de que el identificador de reutilización coincida con lo que ha configurado en la configuración de Storyboard para la celda en cuestión.
James Boutcher

Solo para agregar a esto en un caso de uso ligeramente diferente, estaba volviendo a seleccionar una fila en la vista Master de mi SplitViewController. Esta lógica de fila de reselección estaba en viewDidLoady moviendo esta lógica para viewDidAppeararreglarla.
Craig Conover

No se pudo ingresar en la celda == nil, por lo que mi celda de tableview siempre es nula.
Solid Soft

3
swift 3.0: self.tableView.register (UITableViewCell.classForCoder (), forCellReuseIdentifier: "Cell");
norbDEV

68

Aunque esta pregunta es bastante antigua, existe otra posibilidad: si está utilizando Storyboards, simplemente tiene que configurar CellIdentifier en Storyboard.

Entonces, si su CellIdentifier es "Cell", simplemente configure la propiedad "Identifier": ingrese la descripción de la imagen aquí

Asegúrese de limpiar su construcción después de hacerlo. XCode a veces tiene algunos problemas con las actualizaciones de Storyboard


3
eres increíble, la limpieza hace mucho !! : D
Sandy

2
Nota: si usa un identificador que no sea "Cell", también deberá cambiar su método cellForRowAtIndexPath para usar este identificador en la siguiente línea: static NSString * CellIdentifier = @ "MyCellIdentifier";
gamozzii

55
Una adición importante a esto: la vista de tabla debe tener su atributo "Contenido" establecido en "Prototipos dinámicos", NO en "Celdas estáticas"
Ted Avery

Esta respuesta debe llegar más alto. Muy útil
Sukitha Udugamasooriya

La construcción de limpieza fue esencial después de actualizar la Identifierpropiedad. ¡Gracias!
Crashalot

59

Tuve el mismo problema reemplazando con

static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

   if (cell==nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];

    }

resuelto


Gracias. Esto solo me ahorró un dolor de cabeza. =)
Robert

3
consejo: si usa un - (id) dequeueReusableCellWithIdentifier: forIndexPath:, no necesita verificar si la celda es nula. (IOS6>)
fabricante

Solo me ahorró un dolor de cabeza. =)
Abo3atef

26

El problema es más probable porque configura personalizado UITableViewCellen el guión gráfico pero no usa el guión gráfico para crear una instancia de su UITableViewControlleruso UITableViewCell. Por ejemplo, en MainStoryboard, tiene una UITableViewControllersubclase llamada MyTableViewControllery tiene una dinámica personalizada UITableViewCellllamada MyTableViewCellcon identificador de identificación "MyCell".

Si crea su costumbre UITableViewControllerasí:

 MyTableViewController *myTableViewController = [[MyTableViewController alloc] init];

No registrará automáticamente su tableviewcell personalizado para usted. Tienes que registrarlo manualmente.

Pero si usa storyboard para crear instancias MyTableViewController, así:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyTableViewController *myTableViewController = [storyboard  instantiateViewControllerWithIdentifier:@"MyTableViewController"];

¡Qué buena cosa pasa! UITableViewControllerregistrará automáticamente su celda de vista de tabla personalizada que defina en el guión gráfico para usted.

En su método delegado "cellForRowAtIndexPath", puede crear su celda de vista de tabla de esta manera:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

//Configure your cell here ...

return cell;
}

dequeueReusableCellWithIdentifier creará automáticamente una nueva celda para usted si no hay una celda reutilizable disponible en la cola de reciclaje.

¡Entonces has terminado!


¡El consejo que instantiateViewControllerWithIdentifierusé para iniciar mi viewController me salvó el día!
Lei Zhang

me salvó el día: las células prototipo estaban en el VC vecino con una mesa
Anton Tropashko

Esta es la causa razonable en mi caso.
Nora Alnashwan

19

Solo agregaré que Xcode 4.5 incluye el nuevo dequeueReusableCellWithIdentifier:forIndexPath:
en su código de plantilla predeterminado, un problema potencial para los desarrolladores que esperan el dequeueReusableCellWithIdentifier:método más antiguo.


Me picó! Ahora lo sabré mejor. ;)
spstanley

18

En su guión gráfico, debe configurar el 'Identificador' de su celda prototipo para que sea el mismo que su CellReuseIdentifier "Cell". Entonces no recibirá ese mensaje o necesitará llamar a esa función registerClass:.


2
Gotcha! ¿Dónde está el botón "100 votos a favor"? Esta es la verdadera solución.
Jojo.Lechelt

Pensaría que agregar una nueva tableView en un guión gráfico proporcionará un identificador predeterminado: 'Celda' para usted. Se pasa por alto tan fácilmente, especialmente si está utilizando el llamado 'código libre' en tableView: cellForRowAtIndexPath!
ushika

18

Solución Swift 2.0:

Debe ingresar a su Inspector de atributos y agregar un nombre para su Identificador de celdas:

ingrese la descripción de la imagen aquí

Luego debe hacer que su identificador coincida con su dequeue de esta manera:

let cell2 = tableView.dequeueReusableCellWithIdentifier("ButtonCell", forIndexPath: indexPath) as! ButtonCell

Alternativamente

Si está trabajando con una punta, es posible que deba registrar su clase en su cellForRowAtIndexPath:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {       

    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "SwitchCell")

    // included for context            
    let cell = tableView.dequeueReusableCellWithIdentifier("SwitchCell", forIndexPath:indexPath) as! SwitchCell

    //... continue    
}

La referencia de clase UITableView de Apple dice:

Antes de retirar las celdas, llame a este método o al registerNib: forCellReuseIdentifier: método para indicar a la vista de tabla cómo crear nuevas celdas. Si una celda del tipo especificado no está actualmente en una cola de reutilización, la vista de tabla usa la información proporcionada para crear un nuevo objeto de celda automáticamente.

Si previamente registró una clase o un archivo plumín con el mismo identificador de reutilización, la clase que especifique en el parámetro cellClass reemplaza la entrada anterior. Puede especificar nil para cellClass si desea anular el registro de la clase desde el identificador de reutilización especificado.

Aquí está el código del marco de Apple Swift 2.0:

// Beginning in iOS 6, clients can register a nib or class for each cell.
// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned.
// Instances returned from the new dequeue method will also be properly sized when they are returned.

@available(iOS 5.0, *)
func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String)

@available(iOS 6.0, *)
func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String)

No entiendo de dónde SwitchCell.selfviene?
Gert Cuykens

@GertCuykens SwitchCell es mi UITableViewCell personalizado
Dan Beaulieu

1
Estoy lejos de mi Mac en este momento, pero definitivamente puedo actualizarlo cuando llegue a casa.
Dan Beaulieu

1
Reemplazarlo UITableViewCell.selfparece funcionar para mí. Tal vez agregue una nota en la respuesta
Gert Cuykens

@GertCuykens gracias por señalar eso, he cambiado SwitchCell.self por UITableViewCell.self
Dan Beaulieu

3

Si va con celdas estáticas personalizadas, simplemente comente este método:

//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//    static NSString *CellIdentifier = @"notificationCell";
//    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//    return cell;
//}

y dé a las celdas un identificador en "Inspector de atributos" en el guión gráfico.


3

Te doy la respuesta tanto en el Objetivo C como en Swift. Antes de eso quiero decir

Si usamos el dequeueReusableCellWithIdentifier:forIndexPath:, debemos registrar un archivo de clase o plumín utilizando el método registerNib: forCellReuseIdentifier: o registerClass: forCellReuseIdentifier: antes de llamar a este método como dice Apple Documnetation.

Entonces agregamos registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

Una vez que registramos una clase para el identificador especificado y se debe crear una nueva celda, este método inicializa la celda llamando a su método initWithStyle: reuseIdentifier:. Para celdas basadas en plumillas, este método carga el objeto de celda del archivo plumín proporcionado. Si una celda existente estaba disponible para su reutilización, este método llama al método prepareForReuse de la celda.

en el método viewDidLoad debemos registrar la celda

C objetivo

OPCIÓN 1:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];

OPCION 2:

[self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] forCellReuseIdentifier:@"cell"];

en el código anterior, nibWithNibName:@"CustomCell"dé su nombre de punta en lugar de mi nombre de punta CustomCell

RÁPIDO

OPCIÓN 1:

tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

OPCION 2:

tableView.registerNib(UINib(nibName: "NameInput", bundle: nil), forCellReuseIdentifier: "Cell") 

en el código de arriba nibName:"NameInput"da tu nombre de punta


3

Trabajando con Swift 3.0:

override func viewDidLoad() {
super.viewDidLoad()

self.myList.register(UINib(nibName: "MyTableViewCell", bundle: nil), forCellReuseIdentifier: "Cell")
}



public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myList.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as! MyTableViewCell

return cell
}

2

Pasé horas anoche averiguando por qué mi tabla generada programáticamente se estrelló en [myTable setDataSource: self]; Estuvo bien comentando y apareciendo una mesa vacía, pero fallaba cada vez que intentaba llegar a la fuente de datos;

Tenía la delegación configurada en el archivo h: @interface myViewController: UIViewController

¡Tenía el código fuente de datos en mi implementación y todavía BOOM !, ¡se bloquea cada vez! GRACIAS a "xxd" (nr 9): ¡agregar esa línea de código lo resolvió para mí! De hecho, estoy iniciando una tabla desde un botón IBAction, así que aquí está mi código completo:

    - (IBAction)tapButton:(id)sender {

    UIViewController* popoverContent = [[UIViewController alloc]init];

    UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
    popoverView.backgroundColor = [UIColor greenColor];
    popoverContent.view = popoverView;

    //Add the table
    UITableView *table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)         style:UITableViewStylePlain];

   // NEXT THE LINE THAT SAVED MY SANITY Without it the program built OK, but crashed when      tapping the button!

    [table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    table.delegate=self;
    [table setDataSource:self];
    [popoverView addSubview:table];
    popoverContent.contentSizeForViewInPopover =
    CGSizeMake(200, 300);

    //create a popover controller
    popoverController3 = [[UIPopoverController alloc]
                          initWithContentViewController:popoverContent];
    CGRect popRect = CGRectMake(self.tapButton.frame.origin.x,
                                self.tapButton.frame.origin.y,
                                self.tapButton.frame.size.width,
                                self.tapButton.frame.size.height);


    [popoverController3 presentPopoverFromRect:popRect inView:self.view   permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];



   }


   #Table view data source in same m file

   - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
   {
    NSLog(@"Sections in table");
    // Return the number of sections.
    return 1;
   }

   - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
  {
    NSLog(@"Rows in table");

    // Return the number of rows in the section.
    return myArray.count;
   }

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath    *)indexPath
    {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    NSString *myValue;

    //This is just some test array I created:
    myValue=[myArray objectAtIndex:indexPath.row];

    cell.textLabel.text=myValue;
    UIFont *myFont = [ UIFont fontWithName: @"Arial" size: 12.0 ];
    cell.textLabel.font  = myFont;

    return cell;
   }

Por cierto: el botón debe estar vinculado como IBAction y como IBOutlet si desea anclar el popover a él.

UIPopoverController * popoverController3 se declara en el archivo H directamente después de @interface entre {}


2

FWIW, recibí este mismo error cuando olvidé establecer el identificador de celda en el guión gráfico. Si este es su problema, en el guión gráfico haga clic en la celda de la vista de tabla y configure el identificador de la celda en el editor de atributos. Asegúrese de que el identificador de celda que establezca aquí sea el mismo que

static NSString *CellIdentifier = @"YourCellIdenifier";

2

Tuve el mismo problema, estaba teniendo el mismo error y para mí funcionó así:

[self.tableView registerNib:[UINib nibWithNibName:CELL_NIB_HERE bundle: nil] forCellReuseIdentifier:CELL_IDENTIFIER_HERE];

Tal vez sea útil para alguien más.


2

Configuré todo correctamente en el Storyboard e hice una compilación limpia pero seguí recibiendo el error " debe registrar una punta o una clase para el identificador o conectar una celda prototipo en un storyboard "

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

Se corrigió el error pero todavía estoy perdido. No estoy usando una 'celda personalizada', solo una vista con una vista de tabla incrustada. He declarado el viewcontroller como delegado y fuente de datos y me aseguré de que el identificador de la celda coincida en el archivo. ¿Que está pasando aqui?


1

Esto puede parecer estúpido para algunas personas, pero me atrapó. Estaba recibiendo este error y el problema para mí era que estaba tratando de usar celdas estáticas pero luego agregar dinámicamente más cosas. Si llama a este método, sus celdas deben ser prototipos dinámicos. Seleccione la celda en el guión gráfico y debajo del inspector de atributos, lo primero dice 'Contenido' y debe seleccionar prototipos dinámicos no estáticos.


¡GRACIAS! Este fue exactamente mi problema.
Isaiah Turner

1

Solo un complemento de las respuestas: puede haber un momento en que usted arregle todas las cosas correctamente, pero puede agregar accidentalmente algunas otras IU en usted .xib, como UIButton: ingrese la descripción de la imagen aquí Simplemente elimine la IU adicional, funciona.


1

Asegúrese de que el identificador CellIdentifier == de la celda en un guión gráfico, ambos nombres son iguales. Espero que esto funcione para ti


0

En mi caso, el accidente ocurrió cuando llamédeselectRowAtIndexPath:

La linea era [tableView deselectRowAtIndexPath:indexPath animated:YES];

¡Cambiándolo a [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; FIJO MI PROBLEMA!

Espero que esto ayude a alguien


0

En Swift, este problema se puede resolver agregando el siguiente código en su

viewDidLoad

método.

tableView.registerClass(UITableViewCell.classForKeyedArchiver(), forCellReuseIdentifier: "your_reuse_identifier")

-1

Me encontré con este error porque el identificador de reutilización de la celda estaba mal; un error de novato pero sucede: 1. Asegura que el identificador de reutilización de la celda no tenga faltas de ortografía o letras faltantes. 2. En la misma línea, no olvide los recuentos de capitalización. 3. Los ceros no son "O" (Ohs)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.