Dans le code ARC activé, comment corriger un avertissement concernant un cycle de conservation potentiel, lors de l'utilisation d'une API basée sur des blocs?
L'avertissement:
Capturing 'request' strongly in this block is likely to lead to a retain cycle
produit par cet extrait de code:
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...
[request setCompletionBlock:^{
NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
// ...
}];
L'avertissement est lié à l'utilisation de l'objet request
à l'intérieur du bloc.
responseData
place derawResponseData
, consultez la documentation ASIHTTPRequest.Réponses:
Me répondant:
Ma compréhension de la documentation dit que l'utilisation du mot
block
- clé et la définition de la variable sur nil après l'avoir utilisée dans le bloc devraient être acceptées, mais cela affiche toujours l'avertissement.Mise à jour: je l'ai fait fonctionner avec le mot-clé '_ faible' au lieu de ' _block', et en utilisant une variable temporaire:
Si vous souhaitez également cibler iOS 4, utilisez à la
__unsafe_unretained
place de__weak
. Même comportement, mais le pointeur reste suspendu au lieu d'être automatiquement mis à nil lorsque l'objet est détruit.la source
Le problème se produit car vous attribuez un bloc à la demande qui contient une référence forte à demander. Le bloc conservera automatiquement la demande, de sorte que la demande d'origine ne sera pas désallouée à cause du cycle. Ça a du sens?
C'est juste bizarre parce que vous marquez l'objet de requête avec __block pour qu'il puisse se référer à lui-même. Vous pouvez résoudre ce problème en créant une référence faible à côté .
la source
Cela est dû au maintien de soi dans le bloc. Le bloc sera accédé à partir de soi, et soi est référencé dans le bloc. cela créera un cycle de rétention.
Essayez de résoudre ce problème en créant une référence faible de
self
la source
Parfois, le compilateur xcode a des problèmes pour identifier les cycles de conservation, donc si vous êtes sûr de ne pas conserver le bloc de complétion, vous pouvez mettre un indicateur de compilateur comme celui-ci:
la source
Quand j'essaye la solution fournie par Guillaume, tout va bien en mode Debug mais ça plante en mode Release.
Notez que n'utilisez pas __weak mais __unsafe_unretained car ma cible est iOS 4.3.
Mon code plante lorsque setCompletionBlock: est appelé sur l'objet "request": la requête a été désallouée ...
Donc, cette solution fonctionne à la fois dans les modes Debug et Release:
la source
quelle est la différence entre __weak et __block reference?
la source
Consultez la documentation sur le site Web des développeurs Apple: https://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html#//apple_ref/doc/uid/TP40011029
Il y a une section sur les cycles de rétention au bas de la page.
la source