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
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.
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
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.
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.
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.
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
@ 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
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. –