Quelle est la différence entre une référence __weak et une référence __block?

Je lis la documentation de Xcode, et voici quelque chose qui me trouble:

__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 capture. Si vous utilisez self dans un bloc, le bloc forme une référence forte à self , donc si self également une référence forte au bloc (ce qu’il fait généralement), il en résulte un cycle de référence fort. Pour éviter le cycle, vous devez créer une référence faible (ou __block ) à self en dehors du bloc, comme dans l’exemple ci-dessus.

Je ne comprends pas ce que signifie «un faible (ou un __block )»?

Est

 __block typeof(self) tmpSelf = self; 

et

 __weak typeof(self) tmpSelf = self; 

exactement la même chose ici?

J’ai trouvé un autre morceau dans le document:

Remarque: Dans un environnement __weak ordures, si vous appliquez les modificateurs __weak et __block à une variable, le bloc ne s’assurera pas qu’il rest actif.

Donc, je suis totalement perplexe.

    Des documents sur __block

    Les variables __block sont stockées dans le stockage partagé entre la scope lexicale de la variable et tous les blocs et copies de bloc déclarés ou créés dans la scope lexicale de la variable. Ainsi, le stockage survivra à la destruction de la trame de la stack si des copies des blocs déclarés dans la trame survivent au-delà de la fin de la trame (par exemple, en étant mis en queue quelque part pour une exécution ultérieure). Plusieurs blocs dans une scope lexicale donnée peuvent utiliser simultanément une variable partagée.

    Des documents sur __weak

    __weak spécifie une référence qui ne garde pas l’object référencé en vie. Une référence faible est définie sur nil lorsqu’il n’y a pas de référence forte à l’object.

    Donc, ce sont des choses techniquement différentes. __block permet d’empêcher que votre variable soit copiée de votre étendue externe dans votre étendue de bloc. __weak est un pointeur faible auto délimitant.

    Note j’ai dit techniquement, car 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 uniquement pour iOS4.3 et supérieur, utilisez __weak. Il s’assure que la référence est définie sur nil si la référence de scope globale est en quelque sorte libérée. Si votre projet n’utilise pas ARC ou est pour les versions plus anciennes du système d’exploitation, utilisez __block.

    Il y a une différence subtile ici, assurez-vous de la comprendre.

    EDIT: Une autre pièce du puzzle est __unsafe_unretained. Ce modificateur est presque identique à __weak mais pour les environnements d’exécution antérieurs à 4.3. CEPENDANT, il n’est pas mis à zéro et peut vous laisser avec des pointeurs suspendus.

    En mode de comptage manuel des références, __block id x; a pour effet de ne pas retenir x. En mode ARC, __block id x; conserve par défaut x (comme toutes les autres valeurs). Pour obtenir le comportement du mode de comptage manuel des références sous ARC, vous pouvez utiliser __unsafe_unretained __block id x ;. Comme le nom __unsafe_unretained implique, cependant, une variable non retenue est dangereuse (car elle peut pendre) et est donc déconseillée. Deux meilleures options consistent à utiliser __weak (si vous n’avez pas besoin de prendre en charge iOS 4 ou OS X v10.6) ou à définir la valeur __block sur nil pour interrompre le cycle de conservation.

    documents Apple

    Outre les autres réponses sur __block vs __weak, il existe un autre moyen d’éviter de conserver le cycle dans votre scénario.

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

    Plus d’infos sur @Weakify @Strongify Marco