Comment puis-je éviter cet avertissement dans xcode. Voici l’extrait de code :
Réponses
Trop de publicités?__weak MyClass *self_ = self; // that's enough
self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
if (!error) {
[self_ showAlertWithError:error];
} else {
self_.items = [NSArray arrayWithArray:receivedItems];
[self_.tableView reloadData];
}
};
Et une chose très importante à retenir: ne pas utiliser les variables d'instance directement dans le bloc, l'utiliser comme une des propriétés de la faiblesse de l'objet, exemple:
self.loadingDidFinishHandler = ^(NSArray *receivedItems, NSError *error){
if (!error) {
[self_ showAlertWithError:error];
} else {
self_.items = [NSArray arrayWithArray:receivedItems];
[_tableView reloadData]; // BAD! IT ALSO WILL BRING YOU TO RETAIN LOOP
}
};
et n'oubliez pas de faire:
- (void)dealloc {
self.loadingCompletionHandler = NULL;
}
un autre problème peut apparaître si vous allez passer à la faiblesse de la copie de pas conservées par toute personne de l'objet:
MyViewController *vcToGo = [[MyViewCOntroller alloc] init];
__weak MyViewController *vcToGo_ = vcToGo;
self.loadingCompletion = ^{
[vcToGo_ doSomePrecessing];
};
si vcToGo
sera libéré et puis ce bloc tiré je crois que vous obtiendrez crash non reconnu de sélecteur pour une poubelle qui contient vcToGo_
variable est maintenant. Essayer de la contrôler.
Une meilleure version
__strong typeof(self) strongSelf = weakSelf;
Créer une référence forte à cette version faible que la première ligne, dans votre bloc. Si l'auto existe encore lorsque le bloc commence à s'exécuter et n'a pas retombé à zéro, cette ligne assure qu'il persiste tout au long du bloc de l'exécution de la durée de vie.
Donc, le tout serait comme ceci:
// Establish the weak self reference
__weak typeof(self) weakSelf = self;
[player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(0.1, 100)
queue:nil
usingBlock:^(CMTime time) {
// Establish the strong self reference
__strong typeof(self) strongSelf = weakSelf;
...
[strongSelf.timerDisp setText:[NSString stringWithFormat:@"%02d:%02d",min,current]];
}];
J'ai lu cet article à plusieurs reprises. C'est un excellent article par Erica Sadun sur Comment Éviter Les Problèmes Lors De L'Utilisation De Blocs Et NSNotificationCenter
Dans une autre réponse, Tim a dit:
vous ne pouvez pas se référer à soi-même ou de propriétés sur soi à partir de l'intérieur d'un bloc qui sera fortement retenu par soi-même.
Ce n'est pas tout à fait vrai. C'est OK pour vous de le faire aussi longtemps que vous briser le cycle à un certain point. Par exemple, disons que vous avez un timer qui déclenche qu'a un bloc qui conserve auto et vous gardez aussi une référence forte à la minuterie de l'auto. C'est parfaitement bien si vous savez que vous allez détruire la minuterie à un certain point, et de briser le cycle.
Dans mon cas tout à l'heure, j'ai eu cet avertissement pour du code qui n':
[x setY:^{ [x doSomething]; }];
Maintenant, je sais que clang ne produira que cet avertissement s'il détecte la méthode commence par "set" (et d'un autre cas particulier dont je ne parlerai pas ici). Pour moi, je sais il n'y a pas de danger de conserver boucle, alors j'ai changé le nom de la méthode à "useY:" bien sûr, qui pourrait ne pas être appropriée dans tous les cas et en général, vous aurez envie d'utiliser une référence faible, mais je trouvais ça intéressant de noter ma solution au cas où il aide les autres.