Errore di asserzione in dequeueReusableCellWithIdentifier: forIndexPath:


324

Quindi stavo facendo un lettore rss per la mia scuola e ho finito il codice. Ho eseguito il test e mi ha dato quell'errore. Ecco il codice a cui si riferisce:

- (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];

    }

ecco l'errore nell'output:

2012-10-04 20: 13: 05.356 Reader [4390: c07] * Errore asserzione in - [UITableView dequeueReusableCellWithIdentifier: forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2372/UITableView.m:4460 2012-10-04 20: 13: 05.357 Lettore [4390: c07] * Terminazione dell'app a causa di un'eccezione non rilevata "NSInternalInconsistencyException", motivo: "incapace di dequeue una cella con identificatore Cell - deve registrare un pennino o una classe per l'identificatore o collegare una cella prototipo in uno storyboard ' * In primo stack di chiamate 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: terminate chiamato lanciando un'eccezione

ed ecco il codice che mostra nella schermata di errore:

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

per favore aiuto!


Risposte:


488

Stai usando il dequeueReusableCellWithIdentifier:forIndexPath:metodo. La documentazione per quel metodo dice questo:

Importante: è necessario registrare un file di classe o pennino utilizzando il metodo registerNib:forCellReuseIdentifier:o registerClass:forCellReuseIdentifier:prima di chiamare questo metodo.

Non è stato registrato un pennino o una classe per l'identificatore di riutilizzo "Cell".

Guardando il tuo codice, sembra che ti aspetti che il metodo dequeue ritorni nilse non ha una cella da darti. È necessario utilizzare il dequeueReusableCellWithIdentifier:per quel comportamento:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

Si noti che dequeueReusableCellWithIdentifier:e dequeueReusableCellWithIdentifier:forIndexPath:sono metodi diversi. Vedi doc per il primo e il secondo .

Se vuoi capire perché dovresti mai usarlo dequeueReusableCellWithIdentifier:forIndexPath:, dai un'occhiata a queste domande e risposte .


166
OH MIO DIO. Perché il modello predefinito di Xcode per un UITableViewController ti dà automaticamente dequeueReusableCellWithIdentifier: forIndexPath :? Così inutile.
spstanley,

15
Il dequeueReusableCellWithIdentifer:forIndexPath:(introdotto in iOS6) è un bel miglioramento, dal momento che non è necessario verificare se la cella è nulla. (Quindi UITableViewControllerfunziona in modo simile a UICollectionView) Ma sì, fastidioso che questa modifica non sia un commento nel modello e che il messaggio di asserzione / arresto anomalo non sia più utile.
Jason Moore,

2
Come minimo penseresti che per impostazione predefinita UITableViewCell sarebbe impostato invece di implodere. Baka.
BadPirate

13
L'ultima riga di questa risposta è d'oro: sono stato morso più di una volta usando dequeueReusableCellWithIdentifier:forIndexPath:quando avrei dovuto usare dequeueReusableCellWithIdentifier:.
ele

Questa risposta è perfetta Ho una domanda: ho un tableViewController come controller della vista iniziale. A didSelectRow ... Sto spingendo un altro tableViewController sullo stack di navigazione. Come mai devo solo registrare una cella per il secondo tableViewController, non l'iniziale?
ArielSD

137

Penso che questo errore riguardi la registrazione del pennino o della classe per l'identificatore.

In modo che tu possa mantenere ciò che stai facendo nella tabella view: cellForRowAtIndexPath e semplicemente aggiungere il codice qui sotto nella tua vistaDidLoad:

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

Ha funzionato per me. Spero possa essere d'aiuto.


3
Un piccolo problema con questo: assicurati che l'identificatore di riutilizzo corrisponda a quello che hai impostato nelle impostazioni dello Storyboard per la cella in questione.
James Boutcher,

Solo per aggiungere questo a un caso d'uso leggermente diverso, stavo selezionando nuovamente una riga nella vista Master del mio SplitViewController. Questa logica di riga di riselezione era nella viewDidLoade spostando questa logica per viewDidAppearrisolverla.
Craig Conover,

Impossibile inserire nella cella == zero, quindi la cella della vista tabella è sempre nulla.
Solid Soft

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

68

Sebbene questa domanda sia piuttosto vecchia, esiste un'altra possibilità: se stai usando Storyboard, devi semplicemente impostare CellIdentifier nello Storyboard.

Quindi, se CellIdentifier è "Cell", basta impostare la proprietà "Identifier": inserisci qui la descrizione dell'immagine

Assicurati di pulire la tua build dopo averlo fatto. A volte XCode presenta alcuni problemi con gli aggiornamenti di Storyboard


3
sei fantastico, la pulizia fa molto !! : D
Sandy,

2
Nota: se si utilizza un identificatore diverso da "Cella", è necessario modificare anche il metodo cellForRowAtIndexPath per utilizzare questo identificatore nella seguente riga: NSString statico * CellIdentifier = @ "MyCellIdentifier";
gamozzii,

5
Un'aggiunta importante a questo: la vista della tabella deve avere l'attributo "Contenuto" impostato su "Prototipi dinamici", NON "Celle statiche"
Ted Avery,

Questa risposta deve essere più alta. Molto utile
Sukitha Udugamasooriya,

La pulizia della build era essenziale dopo l'aggiornamento della Identifierproprietà. Grazie!
Crashalot,

59

ho avuto lo stesso problema con la sostituzione

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

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

    }

risolto


Grazie. Questo mi ha appena fatto venire il mal di testa. =)
Robert,

3
suggerimento: se si utilizza un - (id) dequeueReusableCellWithIdentifier: forIndexPath:, non è necessario verificare se la cella è nulla. (IOS6>)
seufagner

mi ha appena salvato un mal di testa. =)
Abo3atef

26

Il problema è molto probabilmente dovuto alla configurazione personalizzata UITableViewCellnello storyboard ma non si utilizza lo storyboard per creare un'istanza di UITableViewControllerchi lo utilizza UITableViewCell. Ad esempio, in MainStoryboard, hai una UITableViewControllersottoclasse chiamata MyTableViewControllere una dinamica personalizzata UITableViewCellchiamata MyTableViewCellcon ID identificativo "MyCell".

Se crei la tua personalizzazione in UITableViewControllerquesto modo:

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

Non registrerà automaticamente la tua vista tabella personalizzata per te. Devi registrarlo manualmente.

Ma se usi lo storyboard per creare un'istanza MyTableViewController, in questo modo:

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

Succede una cosa bella! UITableViewControllerregistrerà automaticamente la cella di visualizzazione tabella personalizzata definita nello storyboard per te.

Nel tuo metodo delegato "cellForRowAtIndexPath", puoi creare la cella della vista tabella in questo modo:

- (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 creerà automaticamente una nuova cella se non è disponibile una cella riutilizzabile nella coda di riciclaggio.

Allora hai finito!


Il consiglio che l'uso instantiateViewControllerWithIdentifierdi init my viewController mi ha salvato la giornata!
Lei Zhang,

mi ha salvato la giornata: le celle prototipo erano nella vicina VC con un tavolo
Anton Tropashko

Questa è la causa ragionevole nel mio caso.
Nora Alnashwan,

19

Aggiungerò semplicemente che Xcode 4.5 include il nuovo dequeueReusableCellWithIdentifier:forIndexPath:
nel suo codice modello predefinito, un potenziale problema per gli sviluppatori che si aspettano il dequeueReusableCellWithIdentifier:metodo precedente .


Mi ha colpito! Adesso lo saprò meglio. ;)
spstanley,

18

Nello storyboard è necessario impostare l '"Identificatore" della cella del prototipo in modo che corrisponda al "Cell" CellReuseIdentifier. Quindi non riceverai quel messaggio o non dovrai chiamare quella registerClass: funzione.


2
Gotcha! Dov'è il pulsante "100 voti positivi". Questa è la vera soluzione.
Jojo.Lechelt

Penseresti che l'aggiunta di un nuovo tableView in uno storyboard fornirà un identificatore predefinito - "Cella" per te. È così facilmente trascurato soprattutto se si utilizza il cosiddetto "codice libero" in tableView: cellForRowAtIndexPath!
ushika,

18

Soluzione Swift 2.0:

Devi andare nella finestra di ispezione degli attributi e aggiungere un nome per l'identificatore delle celle:

inserisci qui la descrizione dell'immagine

Quindi devi far coincidere il tuo identificatore con il tuo dequeue in questo modo:

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

In alternativa

Se lavori con un pennino potresti dover registrare la tua classe nel tuo 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    
}

Il riferimento alla classe UITableView di Apples dice:

Prima di eseguire il dequeueing di qualsiasi cella, chiamare questo metodo o registerNib: forCellReuseIdentifier: metodo per indicare alla tabella come creare nuove celle. Se una cella del tipo specificato non è attualmente in una coda di riutilizzo, la vista tabella utilizza le informazioni fornite per creare automaticamente un nuovo oggetto cella.

Se in precedenza è stato registrato un file di classe o pennino con lo stesso identificatore di riutilizzo, la classe specificata nel parametro cellClass sostituisce la voce precedente. È possibile specificare zero per cellClass se si desidera annullare la registrazione della classe dall'identificatore di riutilizzo specificato.

Ecco il codice dal framework Apples 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)

Non capisco da dove SwitchCell.selfviene?
Gert Cuykens,

@GertCuykens SwitchCell è il mio UITableViewCell personalizzato
Dan Beaulieu,

1
Sono lontano dal mio Mac in questo momento, ma posso sicuramente aggiornarlo quando torno a casa.
Dan Beaulieu il

1
Sostituirlo con UITableViewCell.selfsembra funzionare per me. Forse aggiungi una nota nella risposta
Gert Cuykens il

@GertCuykens grazie per averlo sottolineato, ho cambiato SwitchCell.self per UITableViewCell.self
Dan Beaulieu il

3

Se utilizzi le celle statiche personalizzate, commenta questo metodo:

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

e dai alle celle un identificatore su "Attributes Inspector" nello storyboard.


3

Ti do la risposta sia in Obiettivo C che in Swift. Prima di questo voglio dire

Se utilizziamo dequeueReusableCellWithIdentifier:forIndexPath:, dobbiamo registrare un file di classe o pennino usando registerNib: forCellReuseIdentifier: o registerClass: forCellReuseIdentifier: metodo prima di chiamare questo metodo come dice Apple Documnetation

Quindi aggiungiamo registerNib:forCellReuseIdentifier: or registerClass:forCellReuseIdentifier:

Dopo aver registrato una classe per l'identificatore specificato e deve essere creata una nuova cella, questo metodo inizializza la cella chiamando il suo metodo initWithStyle: reuseIdentifier:. Per le celle basate su pennino, questo metodo carica l'oggetto cella dal file pennino fornito. Se una cella esistente era disponibile per il riutilizzo, questo metodo chiama invece il metodo preparForReuse della cella.

nel metodo viewDidLoad dovremmo registrare la cella

Obiettivo C

OPZIONE 1:

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

OPZIONE 2:

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

nel codice sopra nibWithNibName:@"CustomCell" tuo nome pennino invece del mio nome pennino CustomCell

SWIFT

OPZIONE 1:

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

OPZIONE 2:

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

nel codice sopra nibName:"NameInput"dare il nome del pennino


3

Lavorare 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

Ieri sera ho passato ore a capire perché la mia tabella generata a livello di codice si è bloccata su [myTable setDataSource: self]; Era OK commentare e spuntare un tavolo vuoto, ma si è schiantato ogni volta che ho provato a raggiungere l'origine dati;

Ho configurato la delega nel file h: @interface myViewController: UIViewController

Avevo il codice sorgente dei dati nella mia implementazione e ancora BOOM !, si bloccava ogni volta! GRAZIE a "xxd" (nr 9): l'aggiunta di quella riga di codice l'ha risolto per me! In effetti sto lanciando una tabella da un pulsante IBAction, quindi ecco il mio codice 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;
   }

A proposito: il pulsante deve essere collegato come IBAction e come IBOutlet se si desidera ancorare il popover ad esso.

UIPopoverController * popoverController3 è dichiarato nel file H direttamente dopo @interface tra {}


2

FWIW, ho avuto lo stesso errore quando ho dimenticato di impostare l'identificatore di cella nello storyboard. Se questo è il tuo problema, nello storyboard fai clic sulla cella della vista tabella e imposta l'identificatore di cella nell'editor degli attributi. Assicurati che l'identificatore di cella impostato qui sia uguale a

static NSString *CellIdentifier = @"YourCellIdenifier";

2

Ho avuto lo stesso problema, ho avuto lo stesso errore e per me ha funzionato in questo modo:

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

Forse sarà utile per qualcun altro.


2

Ho impostato tutto correttamente nello Storyboard e ho fatto una build pulita ma ho continuato a ricevere l'errore "è necessario registrare un pennino o una classe per l'identificatore o collegare una cella prototipo in uno storyboard "

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

Correzione dell'errore ma sono ancora in perdita. Non sto usando una "cella personalizzata", ma solo una vista con una vista tabella incorporata. Ho dichiarato il viewcontroller come delegato e origine dati e mi sono assicurato che l'identificatore della cella corrispondesse nel file. cosa sta succedendo qui?


1

Questo potrebbe sembrare stupido per alcune persone, ma mi ha preso. Stavo ottenendo questo errore e il problema per me era che stavo cercando di usare celle statiche ma poi aggiungere dinamicamente più cose. Se stai chiamando questo metodo, le tue celle devono essere prototipi dinamici. Seleziona la cella nello storyboard e sotto la finestra di ispezione Attributi, la prima cosa dice 'Contenuto' e dovresti selezionare prototipi dinamici non statici.


GRAZIE! Questo era esattamente il mio problema.
Isaiah Turner,

1

Solo un supplemento delle risposte: potrebbe esserci un momento in cui hai sistemato tutte le cose, ma potresti accidentalmente aggiungere alcune altre UI in te .xib, come un UIButton: inserisci qui la descrizione dell'immagine Basta eliminare l'interfaccia utente aggiuntiva, funziona.


1

Assicurati che l'identificatore CellIdentifier == della cella in uno storyboard, entrambi i nomi siano uguali. Spero che questo funzioni per te


0

Nel mio caso, l'incidente è avvenuto quando ho chiamatodeselectRowAtIndexPath:

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

Modificandolo in [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; FIXED MY PROBLEM!

Spero che questo aiuti chiunque


0

In Swift questo problema può essere risolto aggiungendo il seguente codice nel tuo

viewDidLoad

metodo.

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

-1

Si è verificato questo errore perché l'identificatore di riutilizzo delle celle era errato - un errore da principiante ma succede: 1. Rende identificativo di riutilizzo delle celle SURE privo di errori di ortografia o lettere mancanti. 2. Sulla stessa linea, non dimenticare i conteggi delle maiuscole. 3. Gli zeri non sono "O" (Ohs)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.