Quelle est la différence entre une référence faible et une référence en bloc?

je suis en train de lire la documentation de Xcode, et voici quelque chose qui me laisse perplexe:

__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

ce qui suit est copié de la documentation:

un bloc constitue une référence forte aux variables qu'il saisit. Si vous utilisez self à l'intérieur d'un bloc, le bloc constitue une référence forte à self , donc si self a également une forte référence au bloc (qu'il n'), une référence forte résultats du cycle. Pour éviter le cycle, vous devez pour créer une référence faible (ou __block ) à soi en dehors du bloc, comme dans l'exemple ci-dessus.

Je ne comprends pas ce que" faible "(ou __block ) signifie?

Est

__block typeof(self) tmpSelf = self;

et

__weak typeof(self) tmpSelf = self;

c'est exactement la même chose ici.

j'ai trouvé une autre pièce dans le document:

Note: dans un environnement de collecte des ordures, si vous appliquez à la fois __weak et __block modificateurs d'une variable, alors le bloc ne garantit pas qu'il est maintenu en vie.

donc, je suis totalement perplexe.

70
demandé sur Josh Caswell 2012-08-02 12:02:58

3 réponses

de la docs environ _ _ bloc

__bloc de variables vivre dans le stockage qui est partagé entre la portée lexicale de la variable et de tous les blocs et le bloc des copies déclarées ou créé au sein de la variable de portée lexicale. Ainsi, le stockage survivra à la destruction du cadre stack si des copies des blocs déclarés dans le cadre survivent au-delà de la fin du cadre (par exemple, en étant interrogées quelque part pour une exécution ultérieure). Plusieurs les blocs dans une portée lexicale donnée peuvent utiliser simultanément une variable partagée.

de la docs environ _ _ faible

__faible indique une référence qui ne garde pas l'objet référencé vivant. Une faiblesse de référence est définie à zéro lorsqu'il n'y a de solides références à l'objet.

donc ce sont des choses techniquement différentes. __block est d'arrêter votre variable d'être copiés à partir de votre portée externe dans votre bloc de portée. __weak est une auto de délimitation de la faiblesse de pointeur.

Note j'ai dit techniquement, parce que pour votre cas ils feront (presque) la même chose. La seule différence est si vous utilisez ARC ou non. Si votre projet utilise ARC et est seulement pour iOS4.3 et plus, utilisez __faible. Il garantit que la référence est fixée à zéro si la référence de portée globale est publiée d'une manière ou d'une autre. Si votre projet n'utilise pas ARC ou est pour des versions plus anciennes du système D'exploitation, utilisez __block.

là est une différence subtile ici, assurez-vous de le comprendre.

EDIT: une Autre pièce du puzzle est __dangereuse_consignes. Ce modificateur est presque le même que __faible mais pour les environnements de pré-exécution 4.3. Cependant, il n'est pas fixé à zéro et peut vous laisser avec des pointes pendantes.

103
répondu Paul de Lange 2012-08-02 08:25:26

en mode manuel de comptage de référence, __block id x; a l'effet de ne pas retenir X. En mode ARC, __bloque l'id x; par défaut, conserve x (comme toutes les autres valeurs). Pour obtenir le comportement manuel de mode de comptage de référence sous ARC, vous pouvez utiliser _ _ unsafe _ _ unretained _ _ block id x;. Comme le nom __unsafe_unretained implique, cependant, avoir une variable non conservée est dangereux (parce qu'elle peut pendouiller) et est donc découragé. Deux meilleures options sont d'utiliser _ _ faible (si vous n'avez pas besoin de supporter iOS 4 ou OS X v10.6), ou mettez la valeur du bloc __à zéro pour briser le cycle de conservation.

apple docs

5
répondu Andrei Shender 2017-01-19 18:04:01

à côté des autres réponses sur __bloc vs __faible, il y a une autre façon d'éviter de retenir cycle dans votre scénario.

@weakify(self);
[self methodThatTakesABlock:^ {
    @strongify(self);
    [self doSomething];
}];

plus d'informations sur @Weakify @Strongify Marco

0
répondu Jun Jie Gan 2018-01-26 08:58:22