Syntaxliste für Blockdeklarationen


277

Die Blocksyntax in Ziel C (und tatsächlich in C, nehme ich an) ist notorisch inkongruent. Das Übergeben von Blöcken als Argumente sieht anders aus als das Deklarieren von Blöcken als ivars, was anders aussieht als das Blockieren von typedefBlöcken.

Gibt es eine umfassende Liste der Blockdeklarationssyntax, die ich zur schnellen Referenz bereithalten könnte?


9
Was ist falsch an "Deklarieren und Erstellen von Blöcken" im Handbuch zur Blockprogrammierung?
Jscs

Antworten:


696

Liste der Blockdeklarationssyntaxen

Lassen Sie während

  • return_typesei der Typ des Objekts / Primitivs / etc. Sie möchten (häufig void) zurückkehren
  • blockName Seien Sie der Variablenname des Blocks, den Sie erstellen
  • var_typesei der Typ Objekt / Primitiv / etc. Sie möchten als Argument übergeben (leer lassen für keine Parameter)
  • varName sei der Variablenname des angegebenen Parameters

Und denken Sie daran, dass Sie so viele Parameter erstellen können, wie Sie möchten.

Blöcke als Variablen

Möglicherweise die häufigste Erklärung.

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

Blöcke als Eigenschaften

Ähnlich wie das Deklarieren von Blöcken als Variablen, jedoch geringfügig anders.

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

Blöcke als Parameter

Beachten Sie, dass sich dies von "Blöcke als Argumente" unterscheidet. In diesem Fall deklarieren Sie eine Methode, die ein Blockargument wünscht.

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

Blöcke als Argumente

Beachten Sie, dass sich dies von "Blöcke als Parameter" unterscheidet. In diesem Fall rufen Sie eine Methode auf, die ein Blockargument mit einem anonymen Block möchte. Wenn Sie bereits eine Blockvariable deklariert haben, reicht es aus, den Variablennamen als Argument zu übergeben.

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

Anonymer Block

Dies ist funktional ein anonymer Block. Die Syntax zum Zuweisen von Blöcken zu Variablen besteht jedoch einfach darin, die Variable einem anonymen Block gleichzusetzen.

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

typedef Block

Auf diese Weise können Sie einen Kurznamen einrichten, auf den wie bei jedem anderen Klassennamen während der Blockdeklaration verwiesen werden kann.

typedef return_type (^blockName)(var_type);

Um sie später blockNameanstelle der Standard-Blockdeklarationssyntax zu verwenden, ersetzen Sie sie einfach.

Inline-Block

Dies ist wohl eine weniger nützliche Verwendung von Blöcken, kann aber dennoch ihren Platz haben. Ein Inline-Block ist ein anonymer Block, der unmittelbar nach der Instanziierung aufgerufen wird.

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

Inline-Blöcke sind in erster Linie zum Versetzen des Bereichs nützlich und entsprechen in etwa einfachen, durch Klammern getrennten Codeabschnitten.

{
   //...
}

Rekursive Blöcke

Auf diese Weise können Sie einen Block von sich aus aufrufen und eine Schleife erstellen, die bei Rückrufen und GCD-Aufrufen verwendet werden kann. Diese Instanziierungsmethode ist frei von Aufbewahrungszyklen in ARC.

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

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

Blöcke zurückgeben

Eine Methode kann einen Block zurückgeben.

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

wie kann eine Funktion, wenn auch etwas seltsam.

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

Nachträge

Wenn ich etwas verpasst habe, lass es mich bitte in den Kommentaren wissen und ich werde sie recherchieren / hinzufügen.

Oh, und in Swift ...

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

Es ist fast so, als wäre es eine Sprachfunktion.


1
@pcperini Eine tolle Liste! Und wie verwende ich die typedef'd Blockdefinition in der Variablendeklaration (1. Element in Ihrer Liste)? Logisch BlockType ^blockVar = Anonymous Blockzeigt Syntaxfehler, auch ohne ^ :(
besonders

14
Irgendwie kann sich mein Gehirn nicht an all diese verschiedenen Syntaxen für Blockdeklarationen erinnern. Ich schaue mir diese Antwort wahrscheinlich einmal pro Woche an. Ich wünschte, ich könnte Ihnen 10 Upvotes dafür geben.
Ben Baron

36
Für solche Antworten benötigen wir eine StackOverflow Hall of Fame.
Bejonbee

1
Ich habe dies in Markdown konvertiert, um es mit einem Viewer zum Drucken zu verwenden. Praktisch! gist.github.com/swizzlr/6268955
Swizzlr

20
Ich glaube, ich brauche das als Tätowierung.
Isaac Overacker


39

Typedef:

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

In der Reihe:

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

Methode:

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

Diese Antwort zeigt, dass es doch nicht so kompliziert ist ... nur 3 verschiedene Syntaxen zum Mischen und Anpassen.
Joseph Chen

4
Die akzeptierte Antwort ist nur eine Kopie dieser Antwort mit unnötigem Aufblähen.
Erik Aigner

16

Die Xcode 4-Snippet-Bibliothek enthält Vorlagen für Blocktypedefs und Inline-Blöcke als Variablen. Sie sind auch über die automatische Vervollständigung ( typedefblockund inlineblock) verfügbar .

Für Blöcke als Argumente für Methoden würde ich empfehlen, a zu deklarieren typedefund dann einfach zu verwenden. Dies erleichtert das Lesen des Codes erheblich.


11

Ich habe einen CompletionBlock für eine Klasse geschrieben, der die Werte eines Würfels zurückgibt, nachdem er geschüttelt wurde:

  1. Definieren Sie typedef mit returnType ( .hobige @interfaceDeklaration)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
  2. Definiere a @propertyfür den Block ( .h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
  3. Definieren Sie eine Methode mit finishBlock( .h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
  4. Insert vorherige definierte Methode in .mDatei und verpflichten finishBlockzu @propertydefiniert vor

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
  5. Um completionBlockeinen vordefinierten Variablentyp an ihn auszulösen (Vergessen Sie nicht zu prüfen, ob der completionBlockvorhanden ist).

    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;

Es wäre gut, den gesamten Prozess Schritt für Schritt zu beschreiben. Blöcke sind schwer zu verstehen, wenn Sie neu bei ios sind ...
Alex Cio

3

Wenn Sie in Xcode 4.2 zurückarbeiten müssen, können Sie auch einen als Eigenschaft deklarierten Block @synthesize, genau wie Sie es mit einer Nicht-Block-Eigenschaft tun würden. Lassen Sie sich nicht von der Blocksyntax überraschen.

Wenn Ihre Blockeigenschaft folgende ist:

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

Dann lautet Ihre @synthesize wie folgt:

@property blockName;

Prost.


Hallo, könnten Sie bitte noch einmal überprüfen .. Ich habe nur versucht, Ihnen zu folgen .. @property blockNamefunktioniert nicht. Ich denke es sollte sein @synthesize blockName;? (zum Synthetisieren eines Blocks)
jeet.chanchawat

oops ... warte du hast schon (indirekt) erwähnt, dass es mit xcode 7 nicht funktioniert.
jeet.chanchawat
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.