Liste de syntaxe de déclaration de blocage


277

La syntaxe des blocs dans l'objectif C (et en fait C, je suppose) est notoirement incongrue. Passer des blocs comme arguments est différent de déclarer des blocs comme ivars, ce qui est différent des typedefblocs ing.

Existe-t-il une liste complète de syntaxe de déclaration de bloc que je pourrais garder à portée de main pour une référence rapide?


9
Quel est le problème avec "Déclarer et créer des blocs" dans le Guide des rubriques de programmation des blocs?
jscs

explication simple de l'utilisation des propriétés de bloc: stackoverflow.com/a/20760583/294884
Fattie

Réponses:


696

Liste des syntaxes de déclaration de bloc

Tout au long, laissez

  • return_typeêtre le type d'objet / primitif / etc. vous souhaitez revenir (généralement void)
  • blockName être le nom de variable du bloc que vous créez
  • var_typeêtre le type objet / primitif / etc. vous souhaitez passer comme argument (laissez vide pour aucun paramètre)
  • varName être le nom de variable du paramètre donné

Et n'oubliez pas que vous pouvez créer autant de paramètres que vous le souhaitez.

Blocs en tant que variables

Peut-être le plus commun pour la déclaration.

return_type (^blockName)(var_type) = ^return_type (var_type varName)
{
    // ...
};

Blocs en tant que propriétés

Tout comme déclarer des blocs en tant que variables, bien que subtilement différents.

@property (copy) return_type (^blockName) (var_type);

Blocs en tant que paramètres

Notez que ceci est distinct de "Blocks as Arguments"; dans ce cas, vous déclarez une méthode qui veut un argument de bloc.

- (void)yourMethod:(return_type (^)(var_type))blockName;

Blocs comme arguments

Notez que ceci est distinct de "Blocks as Parameters"; dans ce cas, vous appelez une méthode qui veut un argument de bloc avec un bloc anonyme. Si vous avez déjà déclaré une variable de bloc, il suffit de passer le nom de la variable comme argument.

[someObject doSomethingWithBlock: ^return_type (var_type varName)
{
    //...
}];

Bloc anonyme

Il s'agit fonctionnellement d'un bloc anonyme, mais la syntaxe d'attribution des blocs aux variables consiste simplement à définir la variable égale à un bloc anonyme.

^return_type (var_type varName)
{
    //...
};

typedef Bloquer

Cela vous permet de configurer un nom court qui peut être référencé comme tout autre nom de classe lors de la déclaration des blocs.

typedef return_type (^blockName)(var_type);

Pour ensuite utiliser plus tard blockName au lieu de la syntaxe de déclaration de bloc standard, remplacez simplement.

Bloc en ligne

Il s'agit sans doute d'une utilisation moins utile des blocs, mais elle peut néanmoins avoir sa place. Un bloc en ligne est un bloc anonyme appelé immédiatement après l'instanciation.

^return_type (var_type varName)
{
    //...
}(var);

Les blocs en ligne sont principalement utiles pour la compensation de portée, et sont à peu près équivalents à de simples morceaux de code séparés par des accolades.

{
   //...
}

Blocs récursifs

Cela vous permet d'appeler un bloc à partir de lui-même, créant une boucle qui peut être utilisée pendant les rappels et les appels GCD. Cette méthode d'instanciation est exempte de cycles de rétention dans ARC.

__block return_type (^blockName)(var_type) = [^return_type (var_type varName)
{
    if (returnCondition)
    {
        blockName = nil;
        return;
    }

    // ...
} copy];
blockName(varValue);

Retour des blocs

Une méthode peut retourner un bloc,

- (return_type(^)(var_type))methodName
{
    // ...
}

comme le peut une fonction, si un peu étrangement.

return_type (^FunctionName())(var_type)
{
    // ...
}

Addendums

Si j'ai oublié quelque chose, faites-le moi savoir dans les commentaires, et je les rechercherai / les ajouterai.

Oh, et dans Swift ...

blockName = (varName: var_type) -> (return_type)

C'est presque comme si c'était une fonction de langue.


1
@pcperini Une grande liste! Et comment utiliser la définition de bloc typedef'd dans la déclaration de variable (1er élément de votre liste)? Logique BlockType ^blockVar = Anonymous Blockaffiche une erreur de syntaxe, sans ^ aussi :(
esp

14
D'une certaine manière, mon cerveau est incapable de se souvenir de toutes ces différentes syntaxes pour les déclarations de bloc. Je regarde probablement cette réponse une fois par semaine. J'aimerais pouvoir vous donner 10 votes positifs pour cela.
Ben Baron

36
Nous avons besoin d'un Temple de la renommée StackOverflow pour des réponses comme celle-ci.
bejonbee

1
J'ai converti cela en Markdown pour une utilisation avec une visionneuse pour l'impression. Pratique! gist.github.com/swizzlr/6268955
Swizzlr

20
Je pense que j'ai besoin de ça comme tatouage.
Isaac Overacker


39

Typedef:

typedef void (^block)(NSString *arg);

En ligne:

void (^block)(NSString *) = ^(NSString *param) {
  // do something....
};

Méthode:

- (void)method:(void (^)(NSString *param))handler

Cette réponse montre que ce n'est pas si compliqué après tout ... seulement 3 syntaxes différentes à mélanger et à assortir.
Joseph Chen

4
La réponse acceptée n'est qu'une copie de cette réponse avec des ballonnements inutiles.
Erik Aigner

16

La bibliothèque d'extraits de code Xcode 4 contient des modèles pour les types de blocs et les blocs en ligne en tant que variables. Ils sont également disponibles via l'auto-complétion ( typedefblocketinlineblock ).

Pour les blocs comme arguments des méthodes, je recommanderais de déclarer un typedef, puis simplement de l'utiliser. Cela rend le code beaucoup plus facile à lire.


11

J'ai écrit un ComplémentBlock pour une classe qui retournera les valeurs d'un dé après qu'il ait été secoué:

  1. Définir typedef avec returnType ( .hau-dessus de la @interfacedéclaration)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
  2. Définissez un @propertypour le bloc ( .h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
  3. Définissez une méthode avec finishBlock( .h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
  4. Insérer la méthode définie précédente dans le .mfichier et validerfinishBlock à @propertydéfinir avant

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
  5. Pour déclencher lui completionBlockpasser un type de variable prédéfini (n'oubliez pas de vérifier s'il completionBlockexiste)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }

7
typedef void (^OkBtnBlock)(id data);
typedef void (^CancelBtnBlock)();

@property (nonatomic, strong) OkBtnBlock okBtnBlock;
@property (nonatomic, strong) CancelBtnBlock cancelBtnBlock;

+ (void)foo:(OkBtnBlock)okBtn andCancel:(CancelBtnBlock)btnCancel;

Ce serait bien de décrire tout le processus étape par étape, les blocs sont difficiles à comprendre si vous êtes nouveau sur iOS ...
Alex Cio

3

Si vous avez besoin de retravailler dans Xcode 4.2, vous pouvez également @ synthétiser un bloc déclaré en tant que propriété, tout comme vous le feriez avec une propriété non bloc. Ne laissez pas la syntaxe des blocs vous jeter.

Si votre propriété de bloc est la suivante:

@property (copy) return_type (^blockName) (var_type);

Alors votre @synthesize est le suivant:

@property blockName;

À votre santé.


Salut, pourriez-vous s'il vous plaît revérifier .. J'essayais juste de vous suivre .. @property blockNamene fonctionne pas. Je pense que ça devrait être @synthesize blockName;? (pour synthétiser un bloc)
jeet.chanchawat

oups ... attendez que vous ayez déjà (indirectement) mentionné qu'il ne fonctionnera pas avec xcode 7.
jeet.chanchawat
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.