9

Ho riscontrato un comportamento strano objc_setAssociatedObject sotto ARC. Si consideri il seguente codice:Oggetti associati Objective-C che perdono sotto ARC

static char ASSOC_KEY; 

@interface DeallocTester : NSObject 
@end 

@implementation DeallocTester 
- (void) dealloc 
{ 
    NSLog(@"DeallocTester deallocated"); 
    //objc_setAssociatedObject(self, &ASSOC_KEY, nil, OBJC_ASSOCIATION_RETAIN); 
} 
@end 

@implementation AppDelegate 
- (void) applicationDidFinishLaunching:(UIApplication *)application 
{ 
    NSObject *test = [[DeallocTester alloc] init]; 
    objc_setAssociatedObject(test, &ASSOC_KEY, [[DeallocTester alloc] init], 
          OBJC_ASSOCIATION_RETAIN); 
} 

Sto creando un'istanza di DeallocTester, poi ho impostato un altro DeallocTester come un oggetto associato per esso, allora entrambi andare fuori del campo di applicazione.

Mi aspetto che lo -dealloc del primo oggetto da chiamare, quindi l'oggetto associato sia deallocato, ma vedo il messaggio "DeallocTester deallocated" stampato solo una volta. Se si decommenta la riga objc_setAssociatedObject in -dealloc, anche il secondo oggetto viene deallocato.

Il riferimento Objective-C indica che gli oggetti associati vengono deallocati automaticamente in caso di distruzione dell'oggetto. È un compilatore/ARC/Qualunque problema o mi manca qualcosa?

Aggiornamento

codice Questo esempio è in realtà di lavoro se lo si esegue da un progetto nuovo di zecca. Ma ho due progetti abilitati ARC che non funziona. Farò qualche ricerca e fornirò un campione migliore.

Aggiornamento 2

Ho riempito un rdar://10636309, Associated objects leaking if NSZombie objects enabled in ARC-enabled project

+0

Se si utilizza LLVM3 + perché stai usando gli oggetti associati ? Puoi semplicemente creare iVar e le proprietà in categorie sulla classe. – Abizern

+0

@Abizern Ho intenzione di aggiungere ivars a 'NSObject', i ivar di AFAIR possono essere aggiunti solo a una categoria di estensione di classe, non a una di classe arbitraria. – iHunter

+0

@Abizern Davvero? Come crei un ivar in una categoria? – jlehr

risposta

9

Ho trovato una fonte di un problema: ho attivato gli oggetti NSZombie in entrambi i miei progetti in cui appare questo errore.

Per quanto ho capito, quando gli oggetti zombie sono abilitati, le istanze normali vengono sostituite con NSZombie in deallocation, ma tutti gli oggetti associati sono lasciati in vita! Attenzione a questo comportamento!

Ho creato un aggiornamento rdar://10636309

: C'è un workaround di Cédric Luthi, e questo problema sembra essere fissato in iOS 6.

+0

Heh, un altro buon motivo per non lasciare 'NSZombie' abilitato di default. – jlehr

+0

@jlehr E quali sono gli altri motivi? Li ho sempre abilitati nei miei progetti e finora non ho visto alcun inconveniente. Mi sto perdendo qualcosa? Grazie. – iHunter

+1

Lasciando abilitati gli zombi è possibile mascherare una serie di problemi e, naturalmente, la tua app perde tonnellate di memoria. – jlehr

1

Il codice che hai postato funziona esattamente come pubblicizzato sotto ARC. Ho riscritto la tua implementazione dealloc per rendere le cose un po 'più ovvie.

- (void)dealloc 
{ 
    NSLog(@"deallocating %@", self); 
} 

Ecco il registro risultante:

2012-01-03 06:49:39.754 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x6878800> 
2012-01-03 06:49:39.756 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x688b630> 

Sei sicuro si sta compilando con ARC abilitato?

+0

Wow! Quale versione di OS/XCode stai usando? – iHunter

+0

L'ho eseguito in Xcode 4.2 su 10.7.2. – jlehr

+0

Anch'io. Ora controllerò di nuovo in un nuovo progetto. – iHunter

Problemi correlati