web-dev-qa-db-fra.com

Block conserve implicitement «soi»; - mais est-ce un comportement voulu?

Hier, ma dernière version iOS n'a pas été avertie sur Xcode. Suite à une mise à niveau vers la version 9.3 (9E145) pendant la nuit, j'ai reçu plusieurs avertissements. Quand j'ai essayé self->score suite à une réponse (1) à une question similaire, les avertissements ont disparu.

Mais dans une version plus récente réponse (2) à la même question, le problème est résolu en modifiant les paramètres. Actuellement, mes paramètres pour Apple LLVM 9.0 - Warnings -Objective C and ARC sont

Conservation implicite de "soi" dans les blocs Oui

Mais je ne comprends pas ce que Block implicitly retains 'self' signifie dans le contexte du code ci-dessous donc je ne peux pas dire si ce comportement est "prévu" ou non. Ou si j'ai résolu un problème ou si je l'ai simplement caché. Ou si la réponse 1 serait meilleure que la réponse 2.

Quelqu'un pourrait-il bien vouloir expliquer ce que Block implicitly retains 'self' signifie dans ce contexte? Merci.

score.alpha = 1.0;

if (sequenceState >= STATES_Count)
{
    [GraphicScore animateWithDuration:8.0f
                                delay:1.0f
                              options:UIViewAnimationOptionCurveEaseOut
                           animations:^{self->score.alpha = 0.0;} // animations:^{score.alpha = 0.0;}
                           completion:^(BOOL finished){ }];
}
[self addSubview:score];
9
Greg

Cet avertissement sur les références implicites à self est utile car en l'absence de cela, quand on regarde le code, il n'est pas toujours évident quels blocs ont le risque d'introduire des cycles de référence forts et lesquels ne le font pas. En encourageant le programmeur à rendre ces références self explicites (comme cela est requis dans les langages de programmation sûrs comme Swift), vous vous retrouvez avec du code où vous pouvez clairement voir si un cycle de référence fort est un problème potentiel ou non.

Donc, je vous encourage à laisser l'avertissement activé, mais allez-y et expliquez ces références implicites self (les ivars) avec self-> ou, si vous utilisez des propriétés, self., comme le conseille la première réponse à laquelle vous avez fait référence.

Ensuite, vous pouvez revoir ces utilisations individuelles des fermetures self et vous assurer qu'elles n'introduisent aucun risque réel de cycles de référence forts. Et s'ils le font, vous pouvez adopter les modèles weakSelf ou weakSelf/strongSelf selon le cas.

18
Rob

Donné:

- (void)bobIsYourUncle {
   ^{score.alpha = 0.0;}();
}

score est une variable d'instance, cette variable d'instance est accessible via self. Étant donné que le bloc peut être mis en file d'attente quelque part et exécuté ultérieurement, le bloc conserve self lorsque le bloc est créé.

Parce que l'accès ivar invisiblement déréférence par self, que retenue implicite n'est pas un peu apparent dans le code. La suggestion plutôt laide du compilateur d'ajouter self-> devant l'ivar rend au moins évident que self est capturé par le bloc.

Donc, oui, c'est le bon comportement. Et, oui, c'est parfois souhaité. Vous pouvez l'éviter en saisissant la valeur de l'ivar avant la création du bloc (dans une variable locale), mais vous devez également savoir que cela modifie l'heure à laquelle la valeur de l'ivar est obtenue et cela pourrait provoquer un changement de comportement.

3
bbum