Question Que signifie le mot clé "__block"?


Que fait exactement le __block mot-clé en Objective-C mean? Je sais que cela vous permet de modifier les variables dans les blocs, mais j'aimerais savoir ...

  1. Que dit-il exactement au compilateur?
  2. Est-ce qu'il fait autre chose?
  3. Si c'est tout, alors pourquoi est-ce nécessaire?
  4. Est-ce dans les docs partout? (Je ne peux pas le trouver).

402
2017-08-16 15:39


origine


Réponses:


Il indique au compilateur que toute variable marquée par lui doit être traitée d'une manière spéciale lorsqu'il est utilisé à l'intérieur d'un bloc. Normalement, les variables et leurs contenus qui sont également utilisés dans les blocs sont copiés, ainsi toute modification apportée à ces variables ne s'affiche pas en dehors du bloc. Quand ils sont marqués avec __block, les modifications effectuées à l’intérieur du bloc sont également visibles à l’extérieur.

Pour un exemple et plus d'infos, voir Le type de stockage __block dans Apple Blocs Sujets de programmation.

L'exemple important est celui-ci:

extern NSInteger CounterGlobal;
static NSInteger CounterStatic;

{
    NSInteger localCounter = 42;
    __block char localCharacter;

    void (^aBlock)(void) = ^(void) {
        ++CounterGlobal;
        ++CounterStatic;
        CounterGlobal = localCounter; // localCounter fixed at block creation
        localCharacter = 'a'; // sets localCharacter in enclosing scope
    };

    ++localCounter; // unseen by the block
    localCharacter = 'b';

    aBlock(); // execute the block
    // localCharacter now 'a'
}

Dans cet exemple, les deux localCounter et localCharacter sont modifiés avant l'appel du bloc. Cependant, à l'intérieur du bloc, seule la modification de localCharacter serait visible, grâce à la __block mot-clé. Inversement, le bloc peut modifier localCharacter et cette modification est visible à l'extérieur du bloc.


482
2017-08-16 15:45



@bbum couvre des blocs en profondeur dans un article de blog et touche le type de stockage __block.

__block est un type de stockage distinct

Tout comme statique, auto et volatile, __block est un type de stockage. Il   indique au compilateur que le stockage de la variable doit être géré   différemment.

...

  Cependant, pour les variables __block, le bloc ne conserve pas. C'est à vous de conserver et de libérer, au besoin.   
...

En ce qui concerne les cas d'utilisation, vous trouverez __block est parfois utilisé pour éviter les cycles de rétention puisqu'il ne retient pas l'argument. Un exemple courant est l'utilisation de soi.

//Now using myself inside a block will not 
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;

25
2017-08-16 15:45



__bloc est un qualificatif de stockage pouvant être utilisé de deux manières:

  1. Marque qu'une variable vit dans un stockage partagé entre la portée lexicale de la variable d'origine et tous les blocs déclarés dans cette portée. Et clang va générer une structure pour représenter cette variable, et utiliser cette structure par référence (pas par valeur).

  2. En MRC, __bloc peut être utilisé pour éviter de conserver les variables d'objet capturées par un bloc. Attention que cela ne fonctionne pas pour ARC. Dans ARC, vous devez utiliser __faible au lieu.

Vous pouvez vous référer à apple doc pour des informations détaillées.


8
2017-07-16 09:26



__block est un type de stockage utilisé pour rendre variables les variables de portée, plus franchement si vous déclarez une variable avec ce spécificateur, sa référence sera passée aux blocs et non à une copie en lecture seule pour plus de détails. Bloque la programmation dans iOS


5
2018-03-26 11:04



Normalement, lorsque vous n'utilisez pas __block, le bloc copie (conserve) la variable, donc même si vous modifiez la variable, le bloc a accès à l'ancien objet.

NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints @"hello"

Dans ces 2 cas, vous avez besoin de __block:

1.Si vous souhaitez modifier la variable à l'intérieur du bloc et attendre qu'elle soit visible à l'extérieur:

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    str = @"how are you";
};
theBlock();
NSLog(@"%@", str); //prints "how are you"

2.Si vous souhaitez modifier la variable après avoir déclaré le bloc et que vous attendez que le bloc voie le changement:

__block NSString* str = @"hello";
void (^theBlock)() = ^void() {
    NSLog(@"%@", str);
};
str = @"how are you";
theBlock(); //prints "how are you"

5
2017-11-01 13:28



Du Bloc Langue Spéc.:

En plus du nouveau type de bloc, nous introduisons un nouveau qualificatif de stockage, __block, pour les variables locales. [testme: une déclaration __block dans un littéral de bloc] Le qualificatif de stockage __block est mutuellement exclusif pour les qualificateurs de stockage locaux existants auto, register et static. [testme] Les variables qualifiées par __block agissent comme si elles se trouvaient dans un stockage alloué récupéré automatiquement après la dernière utilisation de ladite variable. Une implémentation peut choisir une optimisation où le stockage est initialement automatique et seulement "déplacé" vers le stockage alloué (heap) sur une copie de bloc d'un bloc de référence. De telles variables peuvent être mutées comme le sont les variables normales.

Dans le cas où une variable __block est un bloc, il faut supposer que la variable __block réside dans le stockage alloué et, en tant que telle, est supposée référencer un bloc qui se trouve également dans le stockage alloué (le résultat d'une opération Block_copy). Malgré cela, il n'est pas prévu de faire une Block_copy ou une Block_release si une implémentation fournit un stockage automatique initial pour les Blocs. Cela est dû à la condition de concurrence inhérente de potentiellement plusieurs threads qui tentent de mettre à jour la variable partagée et le besoin de synchronisation autour de la disposition des anciennes valeurs et de la copie de nouvelles. Une telle synchronisation dépasse la portée de cette spécification de langage.

Pour plus de détails sur la compilation d'une variable __block, voir Bloquer les spécifications d'implémentation, section 2.3.


2
2017-08-16 15:48



J'espère que ceci vous aidera

Supposons que nous ayons un code comme:

{
     int stackVariable = 1;

     blockName = ^()
     {
      stackVariable++;
     }
}

il donnera une erreur comme "variable n'est pas assignable" parce que la variable de pile à l'intérieur du bloc est par défaut immuable.

l'ajout de __block (modificateur de stockage) avant la déclaration le rend mutable à l'intérieur du bloc __block int stackVariable=1; 


2
2017-07-01 12:31