Vorrei sapere in quale situazione hai utilizzato -retainCount
finora e alla fine i problemi che possono verificarsi usandolo.
Grazie.
Vorrei sapere in quale situazione hai utilizzato -retainCount
finora e alla fine i problemi che possono verificarsi usandolo.
Grazie.
Risposte:
Non dovresti mai usare -retainCount
, perché non ti dice mai nulla di utile. L'implementazione dei framework Foundation e AppKit / UIKit è opaca; non sai cosa viene trattenuto, perché viene mantenuto, chi lo mantiene, quando è stato mantenuto e così via.
Per esempio:
[NSNumber numberWithInt:1]
avrebbe un valore retainCount
di 1. Non è così. È 2.@"Foo"
avrebbe un valore retainCount
di 1. Non è così. È 1152921504606846975.[NSString stringWithString:@"Foo"]
avrebbe un valore retainCount
di 1. Non è così. Ancora una volta, è 1152921504606846975.Fondamentalmente, poiché qualsiasi cosa può trattenere un oggetto (e quindi alterarne retainCount
), e poiché non hai l'origine per la maggior parte del codice che esegue un'applicazione, un oggetto non ha retainCount
significato.
Se stai cercando di rintracciare il motivo per cui un oggetto non viene deallocato, utilizza lo strumento Perdite in Strumenti. Se stai cercando di scoprire perché un oggetto è stato deallocato troppo presto, usa lo strumento Zombi in Strumenti.
Ma non usare -retainCount
. È un metodo davvero inutile.
modificare
Per favore, andate tutti su http://bugreport.apple.com e richiedete che -retainCount
sia deprecato. Più persone lo chiedono, meglio è.
modifica n. 2
Come aggiornamento, [NSNumber numberWithInt:1]
ora ha un retainCount
9223372036854775807. Se il tuo codice si aspettava che fosse 2, il tuo codice ora è danneggiato.
- (NSUInteger)retainCount{return NSUIntegerMax;}
.
retainCount
.
Sul serio. Basta non farlo.
Basta seguire la linee guida di gestione della memoria e rilascia solo ciò che si alloc
, new
o copy
(o qualsiasi cosa hai chiamato retain
su di origine).
@bbum lo ha detto meglio qui su SO , e in modo ancora più dettagliato sul suo blog .
-retainCount
può essere ottenuta (con molti più dettagli) da Instruments e dai suoi strumenti.
retain
, retain
, retain
, autorelease,
autorelease, autorelease
potrebbe essere il risultato perfettamente valido di passare un oggetto attraverso l'API UIKit, per esempio.
Gli oggetti rilasciati automaticamente sono un caso in cui il controllo di -retainCount non è informativo e potenzialmente fuorviante. Il conteggio di conservazione non ti dice nulla su quante volte -autorelease è stato chiamato su un oggetto e quindi quante volte verrà rilasciato quando l'attuale pool di rilascio automatico si esaurisce.
Io non trovo retainCounts molto utile quando si verificata con 'strumenti'.
Utilizzando lo strumento "allocazioni", assicurati che "Conteggi riferimenti record" sia attivato e puoi accedere a qualsiasi oggetto e vedere la sua cronologia keepCount.
Associando allocazioni e rilasci puoi ottenere una buona immagine di ciò che sta accadendo e spesso risolvere quei casi difficili in cui qualcosa non viene rilasciato.
Questo non mi ha mai deluso, inclusa la ricerca di bug nelle prime versioni beta di iOS.
Dai un'occhiata alla documentazione Apple su NSObject, copre praticamente la tua domanda: NSObject keepCount
In breve, keepCount è probabilmente inutile per te a meno che tu non abbia implementato il tuo sistema di conteggio dei riferimenti (e posso quasi garantire che non lo avrai).
Nelle parole di Apple, keepCount è "in genere di nessun valore nel debug dei problemi di gestione della memoria".
Ovviamente non dovresti mai usare il metodo keepCount nel tuo codice, poiché il significato del suo valore dipende da quanti rilasci automatici sono stati applicati all'oggetto e questo è qualcosa che non puoi prevedere. Tuttavia è molto utile per il debug, specialmente quando si cercano perdite di memoria nel codice che chiama metodi di oggetti Appkit al di fuori del ciclo di eventi principale, e non dovrebbe essere deprecato.
Nel tuo tentativo di esprimere il tuo punto di vista hai seriamente sopravvalutato la natura imperscrutabile del valore. È vero che non è sempre un conteggio dei riferimenti. Esistono alcuni valori speciali utilizzati per i flag, ad esempio per indicare che un oggetto non deve mai essere deallocato. Un numero come 1152921504606846975 sembra molto misterioso finché non lo scrivi in esadecimale e ottieni 0xfffffffffffffff. E 9223372036854775807 è 0x7fffffffffffffff in esadecimale. E non è davvero così sorprendente che qualcuno scelga di usare valori come questi come flag, dato che ci vorrebbero quasi 3000 anni per ottenere un keepCount alto quanto il numero maggiore, supponendo che tu abbia incrementato il keepCount di 100.000.000 di volte al secondo.
Quali problemi puoi ottenere dall'usarlo? Tutto ciò che fa è restituire il conteggio di conservazione dell'oggetto. Non l'ho mai chiamato e non riesco a pensare a nessun motivo per farlo. L'ho sovrascritto in singleton per assicurarmi che non vengano deallocati.
retainCount
per la gestione della memoria.
Non dovresti preoccuparti della perdita di memoria fino a quando la tua app non è attiva e in esecuzione e fa qualcosa di utile.
Una volta che lo è, avvia Strumenti e usa l'app per vedere se si verificano davvero perdite di memoria. Nella maggior parte dei casi hai creato un oggetto da solo (quindi lo possiedi) e ti sei dimenticato di rilasciarlo dopo aver finito.
Non cercare di ottimizzare il codice mentre lo scrivi, le tue ipotesi su ciò che potrebbe perdere memoria o richiedere troppo tempo sono spesso sbagliate quando effettivamente usi l'app normalmente.
Prova a scrivere il codice corretto, ad esempio se crei un oggetto usando alloc e simili, assicurati di rilasciarlo correttamente.
-retainCount
.