28 votes

ARC, Blocs et cycles de rétention

Travail sur un projet iOS qui cible 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 alors que 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?

22voto

Jeremy W. Sherman Points 22019

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 en __weak ou __unsafe_unretained variable et ensuite l'utiliser à partir de votre bloc. Il n'y a pas besoin d' __block-qualifier les variables, 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.

1voto

tc. Points 23958

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; }
  • Dans l'ARC de mode, vous avez besoin d'une référence forte (de sorte que vous pouvez l'ajouter à la file d'attente) et une faible/unsafe_unretained de référence

La solution la plus simple ressemble à ceci:

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFHTTPRequestOperation * __unsafe_unretained unretainedOperation = operation;

[operation setCompletionBlock:^ {
  if ([unretainedOperation isCancelled]) {
    return;
  }
  ... do stuff ...
}];

Même si vous briser le cycle de référence, il n'y a aucune raison pour que le Bloc de conserver l' AFHTTPRequestOperation dans le 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 de self plus haut dans la pile d'appel).

La meilleure correction semble être de mise à jour pour la dernière AFNetworking, qui passe à l'opération dans le bloc comme un argument.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X