Dealloc personalizzato e ARC (Objective-C)


208

Nella mia piccola app per iPad ho una funzione "cambia lingua" che utilizza un osservatore. Ogni view controller si registra con il mio osservatore durante il suo viewDidLoad:.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

Quando l'utente preme il pulsante "cambia lingua", la nuova lingua viene memorizzata nel mio modello e l'osservatore viene avvisato e chiama un updateUi:selettore sui suoi oggetti registrati.

Funziona molto bene, tranne quando ho i controller di visualizzazione in un TabBarController. Questo perché quando la barra delle schede viene caricata, recupera le icone delle schede dai controller secondari senza inizializzare le visualizzazioni, quindi viewDidLoad:non viene chiamata, quindi i controller di visualizzazione non ricevono notifiche di modifica della lingua. Per questo motivo, ho spostato le mie registerObject:chiamate nel initmetodo.

Quando mi viewDidLoad:registravo con il mio osservatore, ero solito viewDidUnload:annullare la registrazione. Dal momento che mi sto registrando init, ha molto senso annullare la registrazione dealloc.

Ma ecco il mio problema. Quando scrivo:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

Ottengo questo errore:

ARC proibisce l'invio esplicito di "dealloc"

Dal momento che devo chiamare [super dealloc]per assicurarmi che le superclassi vengano ripulite correttamente, ma ARC lo proibisce, ora sono bloccato. C'è un altro modo per essere informato quando il mio oggetto sta morendo?


Come nota a margine, una situazione del genere può causare una perdita di memoria, che non viene visualizzata nello strumento Perdite. Se dataModel conserva il riferimento all'osservatore (che è la cosa predefinita in ARC, anche per gli ivar), il dealloc non verrà mai chiamato, poiché il conteggio delle trattenute sarà maggiore di zero. Pertanto, potrebbe essere necessario annullare la registrazione manuale dell'osservatore per consentire in primo luogo la chiamata del dealloc.
Błażej Czapp,

Ho implementato qualcosa di simile per le opzioni per destrimani e mancini. L'unico VC che necessita del messaggio è quello attualmente visualizzato. Altri guardano il modello in viewDidLoad o viewDidAppear per apportare modifiche all'interfaccia. Forse qualcosa del genere funzionerebbe meglio.
Doug Watkins,

@BlazejCzapp dal momento che sta usando un UITabBarController e diciamo che UITabBarController conterrà sempre un riferimento al controller registrato (come immagino sia il caso dei suoi controller "figlio"), la perdita di memoria sarà ancora un problema? Non vedo quando verrà assegnato il controller registrato. Grazie
Objectif,

Risposte:


419

Quando usi ARC, semplicemente non chiami [super dealloc]esplicitamente: il compilatore lo gestisce per te (come descritto nel documento ARC di Clang LLVM, capitolo 7.1.2 ):

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

4
Se view contiene un riferimento all'osservatore e l'osservatore contiene un riferimento alla vista, allora abbiamo un riferimento circolare. Quindi il conteggio dei riferimenti della vista è maggiore di 0 e deallocnon viene mai chiamato. Ha senso chiamare [observer unregisterObject:self]in dealloc? Cosa mi sto perdendo?
user443854,

questo vuole lavorare. perché l'osservatore stesso detiene un riferimento al controller. questo impedirà al dealloc di essere chiamato in primo luogo
hasan,
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.