ARC, de Blocs et de Conserver des Cycles
De travail sur un iOS projet qui vise 4.0 et 5.0, à l'aide de l'ARC.
En cours d'exécution dans un problème lié à blocs, l'ARC et la référence à un objet à partir de l'extérieur du bloc. Voici un code:
__block AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlock:^ {
if ([operation isCancelled]) {
return;
}
... do stuff ...
operation = nil;
}];
Dans ce cas, le compilateur émet un avertissement que l'aide de l '"opération" dans le bloc de l'est va conduire à un cycle de conserver. En vertu de l'ARC, __bloc conserve aujourd'hui la variable.
Si j'ajoute __dangereuse_consignes, le compilateur versions de l'objet immédiatement, alors, évidemment, cela ne marchera pas.
Je suis ciblage 4.0 donc je ne peux pas utiliser __faibles.
J'ai essayé de faire quelque chose comme ceci:
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
__block __unsafe_unretained AFHTTPRequestOperation *weakOperation = operation;
mais tout weakOperation n'est pas nul, aucun de ses propriétés sont remplies lorsque l'intérieur du bloc.
Quelle est la meilleure façon de gérer cette situation étant donné le projet de contraintes énumérées ci-dessus?
Vous devez vous connecter pour publier un commentaire.
En supposant que les progrès de garanties, de conserver un cycle pourrait être exactement ce que vous voulez. Vous l'avez explicitement briser le cycle de conserver à la fin du bloc, il n'est donc pas un permanent de conserver cycle: lorsque le bloc est appelé, le cycle est rompu.
Si vous avez quelque chose d'autre en gardant l'opération autour, cependant, vous pouvez stocker une référence dans un
__weak
ou__unsafe_unretained
variable et ensuite l'utiliser à partir de votre bloc. Il n'y a pas besoin de__block
qualifier la variable, sauf si vous pour une raison quelconque besoin de changer la variable de liaison pendant le block; puisque vous n'avez pas de conserver cycle de rompre, vous ne devriez pas avoir à affecter quoi que ce soit de la faiblesse de la variable.#pragma clang diagnostic ignored "-Warc-retain-cycles"
, par le par.Cela semble être le problème décrit par Conrad Stoll dans Des blocs, des Opérations, et de Conserver les Cycles, mais son writeup manque quelques points importants:
__block
ressemble à la Pomme de la façon recommandée d'éviter une référence forte à capturé variables dans la MRC de mode, mais c'est complètement inutile dans l'ARC de mode. Dans ce cas, il est complètement inutile dans l'ARC de mode; il est également inutile de la MRC de mode bien que le plus léger de poids solution de contournement est beaucoup plus prolixe:void * unretainedOperation = operation; ... ^{ AFHTTPRequestOperation * op = unretainedOperation; }
La solution la plus simple ressemble à ceci:
Même si vous briser le cycle de référence, il n'y a aucune raison pour que le Bloc de conserver la
AFHTTPRequestOperation
en premier lieu (en supposant que l'opération se tient en vie jusqu'à ce que le gestionnaire d'achèvement complète, ce qui n'est pas toujours garanti mais est généralement vrai et assumées par l'ARC si elle est appelée à l'aide deself
plus haut dans la pile d'appel).La meilleure correction semble être de mise à jour de la dernière AFNetworking, qui passe à l'opération dans le bloc comme un argument.