2015-07-08 27 views
8

Ho letto post su strong/weak self per interrompere i cicli di conservazione, ma sono ancora confuso su come funzionano. Comprendo l'uso di __weak typeof(self) weakSelf = self per creare un debole riferimento al sé, ma sono confuso su un riferimento forte. A quanto ho capito, il riferimento forte è che esiste un forte riferimento a self in modo che non venga deallocato prima della fine del blocco, giusto? Quindi, perché è necessario avere __strong typeof(self) strongSelf = weakSelf? Questo non finisce per puntare comunque sull'oggetto stesso? Quindi, perché non solo strongSelf = self?Interruzione del ciclo di mantenimento con auto forte/debole

risposta

10

Qualsiasi oggetto non debole di cui si fa riferimento all'interno del blocco avrà come risultato un mantenimento implicito su quell'oggetto, mentre il blocco viene creato. Non eseguito, ma creato.

Se si inizializza lo StrongSelf interno direttamente da sé, si manterrà il valore di self e potenzialmente si verificherà un ciclo di conservazione.

D'altra parte, se si inizializza da weakSelf, si non conservare il valore di weakSelf.

Questo è il motivo del doppio passaggio. Il codice esterno copia il valore di self in weakSelf, ma ARC non aggiunge un retain perché è __weak().

Il blocco "creazione" copia il valore di weakSelf (o almeno, riesce a rendere disponibile il suo valore al momento dell'esecuzione). Non puoi vedere dove lo ha copiato, ma è successo.

In blocco "tempo di esecuzione", il blocco copia il "valore di weakSelf" (che sarà nullo se self è stato deallocato nel frattempo) in strongSelf a cui ARC applica quindi un retain to. Quindi, per la durata del blocco, l'oggetto a cui fa riferimento strongSelf rimarrà in vita, se fosse vivo per cominciare. Se ti fossi affidato solo a weakSelf, potrebbe andare nullo in qualsiasi momento durante l'esecuzione del blocco.

Si noti che il modello debole/forte è cintura e parentesi graffe - molti esempi in realtà si basano sul fatto che il weakSelf andrà a zero, e il blocco diventerà silenziosamente una raccolta di no-ops (messaggi a zero).

I cicli di conservazione di solito si verificano solo se (a) si mantiene un riferimento al blocco in un self.property o (b) si passa il blocco a un altro oggetto (gestore delle notifiche, ecc.) E si dice che l'altro oggetto per dimenticarlo nel tuo dealloc; in entrambi i casi il tuo dealloc non verrà mai chiamato mentre il blocco è attivo.

Quando la gente dice "il modo di fare questa roba è con il modello debole/forte", stanno assumendo il peggiore scenario possibile.

+0

Ooh so 'weakSelf = self' assegna a' weakSelf' una copia di 'self'? Sembra un po 'strano, pensavo che indicasse l'originale "io". è questo a causa del blocco o è così che funziona l'assegnazione delle variabili? – somtingwong

+0

@ user1813076 - No, 'weakSelf = self' non _non_ assegna' weakSelf' a una copia di 'self'. Il 'weakSelf' è un puntatore a' self', un puntatore che imposta a 'nil' quando' self' viene deallocato. – Rob

+0

Questo non è aiutato dalla natura subdolo delle chiusure e della portata variabile. È la variabile attuale "weakSelf" che viene essenzialmente copiata, non l'oggetto a cui punta. –

0

In parole semplici

__weak typeof (auto) weakSelf = auto - Usiamo questo appena prima del blocco,

Questo è solo puntatore a sé, non Retain ciclo iniziato

- Conservazione verrà eseguita se e solo se il blocco verrà eseguito

-> Se lo rendiamo forte, esso avvierà il ciclo di conservazione e consumerà memoria, anche se non chiamiamo blocco

9

Lo schema è:

__weak typeof(self) weakSelf = self; 

[manager someAsynchronousMethodWithCompletionHandler:^{ 
    typeof(self) strongSelf = weakSelf; 
    if (strongSelf) { 
     ... 
    } 
}]; 

L'idea è che il blocco del gestore completamento avrà solo un debole riferimento self, in modo che se self viene rilasciato prima che il blocco completamento è chiamato, allora sarà tranquillamente essere deallocato perché il blocco non ha un forte riferimento ad esso. (Un esempio comune è quando un controller di visualizzazione avvia una richiesta di rete asincrona per aggiornare una vista, se il controller di visualizzazione viene eliminato prima che la richiesta di rete termini, non c'è alcun punto in sospeso sull'istanza del controller di visualizzazione per una vista che è stata interrotta.)

Ma, questo modello weakSelf/strongSelf assicura anche che se succede il contrario, che il blocco completamento è iniziato e incontra la linea strongSelf prima self viene rilasciato, il blocco garantirà che self viene mantenuta per tutta la durata della corsa di quel blocco (cioè non può essere deallocato a metà del funzionamento del blocco di completamento, anche se questo è in esecuzione su un thread diverso). Questo ha un numero di potenziali benefici (che vanno dall'integrità dell'oggetto all'eliminazione delle condizioni di gara). A volte non hai effettivamente bisogno della metà dello "weakSelf/strongSelf dance", ma è uno strumento inestimabile quando necessario.

Se, tuttavia, si aveva una linea all'interno del blocco che detto, typeof(self) strongSelf = self (anziché weakSelf), la semplice presenza di self nel lato destro di tale dichiarazione comporterebbe il blocco mantenere una forte riferimento self davanti , vanificando completamente lo scopo di utilizzare weakSelf in primo luogo.

+3

Non penso che tu abbia lo schema giusto. L'incarico interiore di Sé stesso dal sé dovrebbe essere da weakself. –

+0

Dovrebbe essere 'typeof (self) strongSelf = weakSelf;' all'interno di quel blocco. – JaredH

+0

Lol. Giusto. Fisso. – Rob

1

Non ci sono risposte corrette, ma io davvero non lo so, se sono risposte alla tua Q. Essi spiegano il problema di mantenere cicli con blocchi utilizzando auto in generale, ma il vostro Q era:

Così

perché non solo strongSelf = self?

La risposta a questa Q:

Se si potrebbe fare questo, self sarebbe una parte della chiusura del blocco e sempre essere mantenuto. L'intera storia con il sé debole non avrebbe senso.

0

Un punto deve essere deselezionato che non si stia utilizzando un modello debole/forte per evitare il ciclo di conservazione! Se si utilizza un forte riferimento a se stessi o a weakself, non si evita il ciclo di conservazione. Il ciclo di conservazione viene interrotto dall'ambito della variabile di riferimento! Quando ha raggiunto la fine dell'ambito, la variabile di riferimento è deallocata. Il pattern debole/forte è solo un meccanismo di protezione che impedisce di fare un forte riferimento a zero, poiché prima che il blocco venga creato ed eseguito, self può essere deallocato.