2012-05-22 15 views
6

Fino a cinque minuti ero sicuro che la mia comprensione del conteggio dei riferimenti Objective c è eccellente, ma quando ho iniziato a controllare gli oggetti retainCount sono rimasto molto sorpreso nel vedere ciò che ho visto.Obiettivo c - Conteggio di riferimento

Per esempio myViewController ha un UITableView:

file h

@interface RegularChatViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> 
{ 
    UITableView *_tableView; 
} 
@property (nonatomic, retain) IBOutlet UITableView *tableView; 

di file .m

@synthesize tableView = _tableView; 

- (void)loadView 
{ 
    _tableView = [[UITableView alloc] init]; // STEP ONE 
    NSLog(@"tableView retain count: %d",[_tableView retainCount]); 

    self.tableView.frame = CGRectMake(0, 0, 320, tableHeight); // STEP TWO 
    NSLog(@"tableView retain count: %d",[_tableView retainCount]); 

    [self.view addSubview:self.tableView]; // STEP THREE 
    NSLog(@"tableView retain count: %d",[_tableView retainCount]); 
} 

Con mia grande sorpresa l'ingresso era:

tableView retain count: 1 
tableView retain count: 2 
tableView retain count: 3 

ovviamenteFASE UNO aumento mantenere conteggio da 1 con alloc

So anche che l'aumento FASE TRE mantenere conteggio da 1 con addSubview

Ma cosa sta succedendo nel FASE DUE ??? perché ha aumentato il conteggio dei ritiri ???
c'è qualcosa a che fare con ARC ??

+0

Forse perché '.frame' non può esistere senza la vista tabella e quindi aggiunge il conteggio di conservazione? –

+0

Buona congettura; ma 'frame' restituisce una struttura direttamente; nemmeno un riferimento. Nessuna dipendenza lì. – bbum

risposta

7

Secondo documenti Apple sul NSObject Protocol Reference per il metodo retainCount:

Importante Questo metodo è in genere non ha alcun valore per il debug problemi di gestione della memoria. Poiché qualsiasi numero di oggetti framework può aver conservato un oggetto per contenere riferimenti ad esso, mentre allo stesso tempo i pool di autorelease possono contenere un numero qualsiasi di release posticipate su un oggetto, è molto improbabile che tu possa ottenere informazioni utili da questo metodo.

+1

Infatti. Mi preoccupo molto quando vedo gli sviluppatori che effettuano il logout dei conteggi di mantenimento nel loro codice. Finché segui le regole di proprietà e usi lo strumento Perdite ogni tanto, sei d'oro. –

+0

questo è un sollievo :) grazie – Eyal

2

Non appena si interagisce con qualsiasi metodo quadro o di una funzione di sorta, il metodo retainCount diventa completamente inutile, perché non si sa che cosa queste cose fanno nelle loro scatole nere (si potrebbe aggiungere gli oggetti a autorelease piscine o qualsiasi altra cosa) e non dovresti preoccupartene.

L'utilizzo di retainCount per il debug dei problemi di gestione della memoria è sempre una cattiva idea. Vedi this answer per ancora più motivi per evitarlo.

2

Ho una guida pratica qui: When to use retainCount?

Insomma, retainCount raramente significa che cosa si pensa che sarà. Senza sapere come sono implementati UITableView e UIView, non è possibile che sappia quale dovrebbe essere il conteggio di mantenimento. E non stiamo nemmeno prendendo in considerazione l'autorelease ...

+0

Questa non è davvero una pagina web utile, e odio vederla pubblicata qui. Una sola parola senza spiegazione fornisce semplicemente jollies al poster del collegamento; non aiuta il richiedente un po '. –

+0

Scorri verso il basso? Si noti inoltre che ho incluso tutte le informazioni rilevanti nella risposta. –

+0

La risposta va bene, ovviamente. Non avevo mai fatto scorrere la pagina, no. Con i link in basso, è molto meglio di quanto pensassi, ma non posso essere l'unico a vedere che non c'era nient'altro lì, dal momento che sembra che tu l'abbia configurato in modo che per la maggior parte degli schermi nessuno del contenuto inferiore mostra inizialmente. –

0

Bene nel passaggio due: - utilizzando self. tableView, verrà chiamato il getter della proprietà tableview (che è impostato come retain). Pertanto, poiché la proprietà viene allocata e mantenuta, entrambi mantengono rispettivamente gli aumenti del conteggio.

Ogni volta che si deve allocare una proprietà mantenuta, è necessario sovrascrivere il suo metodo getter e questo è chiamato lazy instantiation.

Assegnare meglio la vista tabella nel relativo getter, ad es.

-(UITableView *) tableView 
{ 
    if(!_tableView) { 
      _tableView = [[UITableView alloc]init]; 
    } 

    return _tableView; 
} 
0

self.tableView.frame volontà retain e autorelease al ritorno il tableView dal getter.