2012-03-21 5 views
5

Ho creato una cella prototipo con identificatore "mainViewTableCell" nel file storyboard e ho collegato la vista tabella principale con una classe di controller personalizzata denominata "NTTableViewController". Ho implementato la funzione "tableView cellForRowAtIndexPath" in NTTableViewController.m come segue:Continua a ricevere nil da dequeueReusableCellWithIdentifier?


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString* MAINVIEW_CELLIDENTIFIER = @"mainViewTableCell"; 
    UITableViewCell *newCell = [tableView dequeueReusableCellWithIdentifier: MAINVIEW_CELLIDENTIFIER]; 

    if (newCell == nil) { 
     newCell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: MAINVIEW_CELLIDENTIFIER]; 
     [newCell autorelease]; 
     newCell.selectionStyle = UITableViewCellSelectionStyleNone; 
    } 

    NTContactItem* currentItem = [self.contactItemContainer objectInContainerAtIndex: indexPath.row]; 
    NSString* firstName = currentItem.firstName; 
    NSString* lastName = currentItem.lastName; 

    NSString* fullName = [firstName stringByAppendingFormat: lastName];  
    [newCell.textLabel setText: fullName]; 
    [newCell.detailTextLabel setText: currentItem.mobilePhone]; 

    return newCell; 
} 

Ma io mantenendo sempre nullo da dequeueReusableCellWithIdentifier e devono creare una nuova istanza di cella ogni volta.

Quindi, cosa c'è che non va?

Il codice: project

Grazie a tutti in anticipo.

+0

Sei sicuro di impostare l'identificatore di questo prototipo di cella a esattamente la stessa stringa nello storyboard? –

+0

@FirozeLafeer Sono sicuro. In effetti ho controllato prima quando ho trovato il problema. –

risposta

26

Con storyboard e visualizzazioni tabella con celle prototipo, [tableView dequeueReusableCellWithIdentifier:] non deve restituire nulla. Anche se questa è la prima cella e non ci sono celle già nella coda di riutilizzo, tableview creerà una nuova istanza della cella prototipo e la restituirà.

Nel tuo caso, il problema era qualcosa di completamente diverso (ho scaricato il tuo progetto perché ero davvero curioso).

Nel delegato dell'applicazione nel metodo application:didFinishLaunchingWithOptions:, si sta inizializzando nuovamente questo tableviewcontroller. Quando si chiama [masterController init], questo chiama [super init], che a sua volta chiama [UITableViewController initWithStyle:].

Ciò fa sì che il controller crei un nuovo UITableView, che è diverso da quello nello storyboard. Quel nuovo UITableView non ha celle prototipo, ed ecco perché dequeueReusableCellWithIdentifier: restituisce zero.

La lezione, naturalmente, è non reinizializzare un oggetto Objective-C che è già stato inizializzato. Quando il controller della vista tabella viene caricato dallo storyboard, il meccanismo di caricamento lo inizializzerà con initWithCoder:. Pertanto, se è necessario eseguire alcune operazioni di inizializzazione personalizzate (ad esempio impostando NSMutableArray nel tuo caso), basta eseguire l'override di initWithCoder: e/o awakeFromNib.

È possibile eseguire l'override di questi metodi in base alle esigenze, ma non chiamare . Entrambi i modelli initWithCoder: e awakeFromNib verranno richiamati dal meccanismo di caricamento Storyboard/pennino.

Se tutto è corretto, non è necessario creare celle qui a livello di codice. Questo bit di codice non dovrebbe essere necessario:

// This bit is unnecessary with storyboards:  
if (newCell == nil) { 
    newCell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleSubtitle reuseIdentifier: MAINVIEW_CELLIDENTIFIER]; 
    [newCell autorelease]; 
    newCell.selectionStyle = UITableViewCellSelectionStyleNone; 
} 

Spero che questo aiuti.

+0

Adesso tutto funziona bene. Il motivo per cui ho chiamato [masterController init] è che l'init di masterController non è stato chiamato affatto, lasciando la proprietà NSMutableArray non inizializzata. Non sapevo che initWithCoder può fare lo stesso di init e verrà chiamato automaticamente durante il processo di caricamento dello storyboard. E ho bisogno di saperne di più sul meccanismo di caricamento del file storyboard/pennino. Grazie! –

+0

Questo mi stava facendo impazzire tutto il giorno. Stavo chiamando un init personalizzato (la vecchia fonte prima degli storyboard) da una fonte successiva alla destinazione che ricreava la tabellaView proprio come mostrato qui. Una volta passati i valori utilizzando il metodo prepareForSegue, tutti i miei riutilizzatori automatici hanno funzionato correttamente. Grazie Firoze! –

+0

Ho avuto lo stesso problema e ho istanziato il mio tableviewcontroller usando lo storyboard instatiateViewControllerWithIdentifier: e ora tutto funziona bene – Claus

1

Le celle di tabella diventano riutilizzabili solo quando sono nascoste, quindi è necessario avere solo il numero di celle attualmente visualizzate in memoria. Quante celle stai visualizzando e quante sono allocate?

+0

Ho creato un nuovo progetto usando il modello "Master-Detail Application" fornito da Xcode. Funzione dequeueReusableCellWithIdentifier ha restituito qualcosa ma zero quando viene creata la prima cella. Perchè così? –

2

Dopo aver letto la risposta di @ Firoze ho risolto il mio problema che mi perseguitava da giorni ... e ho trovato un'altra soluzione. So che alla domanda è già stata data una risposta, ma questo potrebbe aiutare qualcuno.

Nel mio caso ho eseguito alcuni refactoring (ho estratto un nuovo TableViewController), e in seguito ho ricevuto celle nil restituite da dequeueReusableCellWithIdentifier.

La correzione per me è stato quello di fare questo invece di chiamare alloc/init sul mio ViewController in didSelectRowAtIndexPath:

UIStoryboard* sb = [UIStoryboard storyboardWithName:@"MainStoryboard" 
               bundle:nil]; 

MyTableViewController* controller = [sb instantiateViewControllerWithIdentifier: 
            @"MyTableViewController"]; 

(Poi chiamo [self.navigationController pushViewController:controller animated:YES]; - non il modo più pulito, forse, ma funziona)

1

Just in caso potrebbe aiutare qualcuno in futuro ... Nel mio caso ho dimenticato di cambiare in Contenuto TableView (Storyboard) da "celle statiche" a "Prototipi dinamici".

0

Causa tipica:

[tableView dequeueReusableCellWithIdentifier: @"id"]; non corrisponde Xcode> Attributo ispettore>Table View cellulare>Identifier> id