2012-09-27 13 views
6

Lavoro come parte di un grande team che lavora su un codice legacy iOS con un ambiente iOS di destinazione di 4.3 e versioni successive. Ho visto altri sviluppatori controllare classi che scendono da NSObject ma non hanno un metodo dealloc. Ho anche visto i discendenti UIViewController che non includono i metodi viewDidUnload. Quando chiedo di questo codice la solita risposta è "Non preoccuparti, ARC si occupa di questo ora".I metodi 'dealloc' e 'viewDidUnload' sono ancora necessari quando si utilizza ARC, pre-iOS6?

Capisco che viewDidUnload viene chiamato quando condizioni di memoria iOS esperienze bassi, con l'obiettivo di liberare la memoria con il rilascio di oggetti che possono essere ricreati chiamando viewDidLoad, e che dealloc viene chiamato quando il conteggio di conservare un oggetto colpisce zero. Per gli oggetti e discendenti di UIViewController, questo può significare che "viewDidUnload" può essere chiamato o meno prima di dealloc.

Quindi, ecco la mia domanda: sono ancora necessari i metodi dealloc e viewDidUnload quando si utilizza ARC su versioni iOS precedenti a iOS 6?

Se la risposta è "Sì!", allora avrò bisogno di buoni motivi e/o documentazione per portare l'argomento.

In attesa di vostre risposte. (Grazie a Tommy per avermi aiutato a stringere la mia domanda.)

risposta

14

viewDidUnloadis deprecated. Quindi, indipendentemente da ARC, non solo non ne hai bisogno, ma non dovresti usarne uno. La giustificazione dichiarata è che i punti di vista non vengono più eliminati dagli avvertimenti di memoria insufficiente (presumibilmente perché ora contribuiscono troppo poco al totale per meritare il colpo di risposta); Non sarei sorpreso se parte della giustificazione fosse che molte persone pensavano che avrebbero potuto rilasciare tutte le risorse create in viewDidLoad all'interno di viewDidUnload e che da sole avrebbero impedito le perdite. Ciò non è vero perché viewDidUnload è chiamato solo se la vista viene scaricata a causa di un avviso di memoria insufficiente. Non è chiamato nel normale ciclo di vita.

Sotto ARC's new rules:

Si può implementare un metodo dealloc se avete bisogno di gestire le risorse diversi da rilasciare variabili di istanza. Non è necessario a (anzi non si può) rilasciare le variabili di istanza

EDIT: per commentare 4.3+ specificamente ...

ARC non attuerà una versione di viewDidUnload per voi.Il punto del ciclo viewDidLoad/viewDidUnload consisteva nel fatto che se si sostituisce una qualsiasi parte della gerarchia della vista per qualsiasi motivo, si verificherà che non venga rilasciato automaticamente in seguito a un avviso di memoria insufficiente, ma in tal caso non si otterrà alcun beneficio perché non appena la vista viene caricata, qualunque cosa tu abbia conservato verrà sostituita con una nuova copia. Quindi, se hai strongIBOutlet s per le viste che si trovano all'interno della gerarchia sotto self.view comunque idealmente le annulleresti durante il periodo viewDidUnload. Anche se hai riferimenti weak, è un buon posto per evitare di portare avanti eventuali puntatori penzolanti.

A partire da iOS 5 è possibile avere riferimenti deboli a zero automatico, quindi l'utilizzo di quelli e non l'implementazione di viewDidUnload sarebbe la strada da percorrere se si supportava 5+. Per 4.3 se si utilizzano riferimenti forti e si omette lo viewDidUnload, si potrebbe finire per impedire una risposta esauriente a un avviso di memoria insufficiente come vorrebbe Apple ma non si verificherà alcuna perdita di memoria. Se utilizzi riferimenti deboli, devi essere un po 'cauto nel non riferirti a nessuno di quegli oggetti nei momenti in cui potresti non avere una vista (cioè, ogni volta che non sei in mostra ma la vista è già stata caricata in precedenza - setter sul controller che regola anche una vista ma che sono influenzati da un altro sono un classico esempio, come dire se stavi aggiornando un campo con l'osservazione dei valori-chiave).

È possibile utilizzare "Simula memoria avviso" del simulatore per testare e eseguire il debug di tali elementi in misura limitata.

Il dealloc che ARC fornisce sarà lo stesso indipendentemente dalla versione di iOS. Tuttavia coprirà solo oggetti Objective-C. Quando dicono che non è possibile rilasciare variabili di istanza, significa che nel senso letterale di inviare il messaggio release a loro. Supponendo che tu abbia oggetti Core Foundation o che hai eseguito l'allocazione di memoria C pura, ti consigliamo di implementare uno dealloc che disponga di tutti questi.

Ovviamente gli strumenti e lo strumento Perdite sono i modi per testare e eseguire il debug di quell'area; fare attenzione ogni volta che la memoria è trapelata per verificare se il tipo di oggetto che ha creato quella memoria viene anche trapelato. L'oggetto immediato può andare bene ma le sue allocazioni appariranno nell'elenco trapelato se non lo fosse dealloc perché qualcun altro l'ha fatto trapelare.

+0

Siamo spiacenti, @ Tommy, non sono stato abbastanza chiaro nella mia domanda sulla versione iOS di destinazione. Aggiornerà la domanda in base alla tua risposta. :) – tychoD

+0

Grazie, questo ha risposto alla mia domanda. : D – tychoD

+0

devo annullare tutti i miei @properties nel dealloc()? –

6

viewDidUnload è ora deprecato e non viene più chiamato dal sistema (come da iOS 6). Non è mai stato così utile come sperava Apple, ed è stato più difficile di quanto valesse. Questo non ha nulla a che fare con ARC.

dealloc spesso non è richiesto in ARC, ma è comunque necessario in situazioni in cui è necessaria la gestione delle risorse non ARC. Ad esempio, se è necessario utilizzare free() o altrimenti rilasciare una risorsa. È anche un buon posto per rimuoverti come osservatore o delegato. Ma molte classi ora non richiedono dealloc.

Problemi correlati