212 votes

Auto capture fortement dans ce bloc est susceptible d’entraîner un cycle de conserver

Comment puis-je éviter cet avertissement dans xcode. Voici l’extrait de code :

520voto

Tim Points 33042

La capture de ici est à venir avec votre accès à la propriété implicite de -vous ne pouvez pas faire référence à ou propriétés sur de dans un bloc qui est fortement retenu par `` .

Vous pouvez contourner cela en créant une référence faible à avant d’accéder à à l’intérieur de votre bloc :

53voto

iiFreeman Points 1521
__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.

46voto

Warif Akhand Rishi Points 3407

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

15voto

Chris Suter Points 1938

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.

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