2011-10-07 15 views
35

C'è una domanda simile a questo su SO here, tuttavia voglio solo chiarire qualcosa che non è stato completamente spiegato lì.IBOutlet e viewDidUnload sotto ARC

Capisco che tutti i delegati e gli outlet - in pratica ogni riferimento a un oggetto "genitore", per essere un buon cittadino e pensare al grafico dell'oggetto per un minuto - dovrebbero azzerare riferimenti deboli. A causa della natura dell'azzeramento dei puntatori deboli che scendono automaticamente a zero sul conteggio di mantenimento dell'oggetto referenziato che raggiunge lo zero, ciò significa che l'impostazione di IBOutlet a zero in viewDidUnload non è più necessaria?

Quindi, se dichiaro il mio sfogo in questo modo:

@property (nonatomic, weak) IBOutlet UILabel *myLabel; 

Ha il seguente codice ha alcun effetto?

- (void)viewDidUnload 
{ 
    self.myLabel = nil; 

    [super viewDidUnload]; 
} 
+0

Vorrei gentilmente sapere il motivo del voto negativo? – Stuart

+0

Ero curioso anche della risposta, quindi ho votato per contrastare. Non conosco la risposta ... – bryanmac

risposta

15

Basta fare un po 'di ricerca ...

Da quanto ho capito, debole è simile ad assegnare, nel senso che sono entrambi riferimenti deboli.

Tuttavia, assegnare non crea un riferimento di azzeramento. Ad esempio, se l'oggetto in questione viene distrutto e si accede a tale proprietà, si otterrà un BAD_ACCESS_EXCEPTION.

Le proprietà deboli vengono azzerate automaticamente (= nil) quando l'oggetto a cui fa riferimento viene distrutto.

In entrambi i casi, non è necessario impostare la proprietà su zero, in quanto non contribuisce al conteggio di conservazione dell'oggetto in questione. È necessario quando si utilizzano le proprietà di conservazione.

Apparentemente, ARC introduce anche una nuova proprietà "strong", che è la stessa di "retain"?

Research fatto here

+1

Grazie per la risposta. Capisco il funzionamento del riferimento debole, la mia domanda è più relativa ai meccanismi alla base di 'viewDidUnload'. In altre parole, è sempre il caso che la vista forzerà il riferimento debole a 'nil' seguendo direttamente la chiamata' viewDidUnload'? – Stuart

+2

Ancora, ** a quanto ho capito **, la vista e le sue sottoviste verranno rilasciate quando viene rimossa dal display. Poiché, debole non incrementa il conteggio del rilascio e viene azzerato quando il suo riferimento viene distrutto, non dovrebbe essere necessario. –

+1

Scusa, devo aver perso quella parte della tua risposta quando l'ho letta la prima volta. – Stuart

11

ho fatto un po 'di test e sembra che il codice del metodo di viewDidUnloadè inutile. A sostegno di questa, la documentazione per viewDidUnload fare in realtà dicono:

Con il tempo questo metodo viene chiamato, la proprietà View è pari a zero.

Indicazione che il riferimento debole deve essere impostato su nil automaticamente.

+3

Questa è anche la mia comprensione. Ma perché Xcode inserisce le istruzioni '' self setMySubview: nil] 'in' viewDidUnload' quando crea deboli punti vendita? –

+2

Penso che _could_ sia una caratteristica lasciata dal codice pre-ARC, nello stesso modo in cui quando chiedi a Xcode di generare una sottoclasse 'NSManagedObject' per Core Data le proprietà generate sono impostate su' retain' invece di 'strong '. Sebbene nel caso dei punti vendita essi siano creati come "deboli". La mia ipotesi è che non sia intenzionale. – Stuart

+0

Sono d'accordo. l'interfaccia utente di Interface Builder è probabilmente errata sul lato della cautela quando si esegue il drag-and-drop per creare punti vendita nel codice. Quelle impostazioni nul possono essere rimosse in modo sicuro finché si utilizza ARC e il riferimento debole sulle prese in questione. –

3

Dalla mia comprensione di come vengono gestiti gli outlets in ARC se si utilizza un riferimento debole, non è necessario aggiungere nulla a viewDidUnload poiché sarà già nullo. Così facendo è ridondante.

Tuttavia, se si dispone di forti punti di vendita, quale mela dice che si dovrebbe fare se si punta a un elemento di livello superiore nel pennino, allora si dovrebbe sicuramente continuare ad aggiungere la linea appropriata in viewDidUnload per annullare questi.

+0

Voglio sapere, se ho definito questo '@property (nonatomico, forte) IBOutlet UILabel * myLabel;', ho bisogno di definire 'self.myLabel = nil;' nella funzione 'viewDidUnload'. – BlackMamba

5

Ho alcune prove empiriche per sostenere che gli IBOutlet sono già impostati su zero automaticamente. Ecco quello che ho fatto:

  1. ho istituito Ivars esplicite per le mie proprietà IBOutlet (@synthesize myLabel = myLabel_) in modo che io possa poi ispezionare i loro valori nel debugger.
  2. Ho abilitato un punto di interruzione sulla prima riga di viewDidUnload.
  3. Ho organizzato la chiamata a viewDidUnload simulando un avviso di memoria.
  4. Ho controllato i valori degli ivars espliciti che ho associato alle mie proprietà di IBOutlet.

Gli ivars espliciti avevano tutti nil come valore quindi ho raggiunto il punto di interruzione.

0

A partire da iOS 5 e OS X 10.7, weak produce un puntatore di azzeramento automatico. Ciò significa che quando l'oggetto appuntito viene rilasciato, il puntatore viene impostato automaticamente su nil (per i dettagli, vedere Zeroing Weak References in ARC).

Quindi, sotto iOS 5+ e OS X 10.7 e versioni successive, non è utile per impostare le weakIBOutlet immobili da nil manualmente nel metodo viewDidUnload: quando la visualizzazione principale viene scaricato, tutti i suoi subviews verranno rilasciati, in modo che il proprietà correlate sono impostate su nil.

Problemi correlati