31

Ho passato il mio progetto a ARC e non capisco se devo usare strong o weak per IBOutlets. Xcode fare questo: nel costruttore di interfaccia, se un creare un UILabel per esempio, e lo collego con assistente al montaggio alla mia ViewController, è creare questo:debole o forte per IBOutlet e altri

@property (nonatomic, strong) UILabel *aLabel; 

utilizza il strong, invece ho letto un tutorial sul sito RayWenderlich che dica questo:

Ma per queste due proprietà particolari ho altri piani. Invece di strong, li dichiareremo come weak.

@property (nonatomic, weak) IBOutlet UITableView *tableView; 
@property (nonatomic, weak) IBOutlet UISearchBar *searchBar; 

Weak è il rapporto raccomandato per tutti uscita proprietà. Questi oggetti di vista sono già parte della gerarchia della vista del controllore di vista e non devono essere conservati altrove. Il grande vantaggio di dichiarare i tuoi punti vendita weak è che ti fa risparmiare tempo scrivendo il metodo viewDidUnload .

Attualmente il nostro viewDidUnload assomiglia a questo:

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    self.tableView = nil; 
    self.searchBar = nil; 
    soundEffect = nil; 
} 

È ora possibile semplificare al seguente:

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    soundEffect = nil; 
} 

Quindi utilizzare weak, al posto del strong, e rimuovere il set su nil nel videDidUnload, invece Xcode usa th e strong e utilizzare self... = nil nello viewDidUnload.

La mia domanda è: quando devo usare strong e quando weak? Voglio anche utilizzarlo per l'obiettivo di distribuzione iOS 4, quindi quando devo usare lo unsafe_unretain? Chiunque può aiutarmi a spiegarmi bene con un piccolo tutorial, quando usi strong, weak e unsafe_unretain con ARC?

risposta

69

Una regola empirica

Quando un genitore ha un riferimento ad un oggetto figlio, è necessario utilizzare un riferimento strong. Quando un bambino ha un riferimento al suo oggetto genitore, dovresti usare un riferimento weak o uno unsafe_unretained (se il primo non è disponibile). Uno scenario tipico è quando si affrontano i delegati. Ad esempio, un UITableViewDelegate non conserva una classe controller che contiene una vista tabella.

enter image description here

Ecco un semplice schema per presentare i principali concetti.

Supponiamo che i primi riferimenti A, B e C siano strong. In particolare, C ha un ref strong per il suo genitore. Quando obj1 viene rilasciato (da qualche parte), il riferimento A non esiste più ma si ha una perdita poiché c'è un ciclo tra obj1 e obj2. Parlando in termini di numero di ritardi (solo per scopi esplicativi), obj1 ha un conteggio di ritenzione di 2 (obj2 ha un riferimento strong), mentre obj2 ha un conteggio di ritenzione di 1. Se obj1 è rilasciato, il suo conteggio di ritenzione è ora 1 e il suo metodo dealloc non viene chiamato. obj1 e obj2 rimangono ancora in memoria ma nessuno ha un riferimento a loro: Perdita.

Sul contato, se solo A e B sono strong ref e C è qualificato come weak tutto è ok. Non hai perdite. Infatti, quando viene rilasciato obj1, rilascia anche obj2. Parlando in termini di conteggi di mantenimento, obj1 ha un conteggio di ritenzione di 1, obj2 ha un conteggio di ritenzione di 1. Se obj1 è rilasciato, il suo conteggio di ritenzione è ora 0 e viene chiamato il suo metodo dealloc. obj1 e obj2 vengono rimossi dalla memoria.

Un semplice suggerimento: iniziare a pensare in termini di oggetto grafico quando si tratta di ARC.

Sulla prima domanda, entrambe le soluzioni sono valide quando si gestiscono XIB. In generale i riferimenti weak vengono utilizzati quando si gestiscono cicli di memoria. Per quanto riguarda i file XIB, se si utilizza strong è necessario impostare nil in viewDidUnload poiché se non si esegue questa operazione, in condizioni di memoria insufficiente, si potrebbero causare perdite impreviste. Non li rilascerai in dealloc perché ARC lo farà per te. weak invece non ha bisogno di tale trattamento poiché, quando l'oggetto di destinazione viene distrutto, tali valori vengono impostati automaticamente come nil. Non ci sono più puntatori penzolanti.

Se siete interessati, vi consiglio davvero di leggere friday-qa-2012-04-13-nib-memory-management per Mike Ash.

Riguardo alla seconda domanda, se è necessario supportare iOS 4, anziché weak è necessario utilizzare unsafe_unretained.

All'interno di SO ci sono molte domande/risposte.Ecco le principali:

How do I replace weak references when using ARC and targeting iOS 4.0?

What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

using ARC, lifetime qualifier assign and unsafe_unretained

strong/weak/retain/unsafe_unretained/assign

Speranza che aiuta.

Aggiornamento

Come per il commento di shaunlim, a partire da iOS 6 viewDidUnload metodo è deprecato. Qui suggerisco davvero di vedere la risposta di Rob: iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?.

+0

grazie per la risposta – Piero

+0

tu dici che, per iboutlet se uso strong devo usare nil in viewdidunload, e per memoria bassa non ho perdite, invece con weak non devo usare nil in videwdidunlaod, e per memoria bassa avviso è meglio la soluzione forte o il debole? – Piero

+0

È lo stesso. L'uso di 'weak' ti consente di risparmiare tempo scrivendo a mano il codice (due righe nel tuo caso). Ma Xcode lo fa per te. La mia opinione personale Mi piace usare 'forte'. –

11

È possibile utilizzare debole per gli oggetti che sono collegati tramite IBOutlets agli oggetti in IB perché in questo caso gli oggetti saranno lì fino a quando il superview è lì. Questo perché la superview ha un forte puntatore alle sue sottoview.

Se il puntatore che si sta definendo è l'unico puntatore a un oggetto, è necessario dichiararlo come forte.

Se sei uno sviluppatore registrato, ti consiglio vivamente di dare un'occhiata ai video di WWDC11 e WWDC12.Un'altra buona risorsa è lo sviluppo podcast di iOS da Stanford.

+0

I video WWDC12 sono ancora disponibili? – borrrden

+0

Sì, lo sono! Molto veloce quest'anno. – dasdom

+0

ok, ma non capisco, la mia domanda copre anche unsafe_unretain, ma per IBOutlet mi sto spiegando bene, perché la mela usa forte? ... invece di usare debole? ... quindi devo seguire la mela? o segui il tutorial di raywenderlich dove scrivo sopra uno snippet che usa debole? – Piero