Elenco sintassi dichiarazione di blocco


277

La sintassi del blocco in Objective C (e in effetti C, presumo) è notoriamente incongrua. Il passaggio di blocchi come argomenti ha un aspetto diverso rispetto alla dichiarazione di blocchi come ivars, che ha un aspetto diverso rispetto ai typedefblocchi.

Esiste un elenco completo della sintassi della dichiarazione di blocco che potrei tenere a portata di mano per una rapida consultazione?


9
Cosa c'è di sbagliato in "Dichiarazione e creazione di blocchi" nella Guida agli argomenti di programmazione dei blocchi?
jscs

spiegazione semplice di usare proprietà del blocco: stackoverflow.com/a/20760583/294884
Fattie

Risposte:


696

Elenco delle sintassi della dichiarazione di blocco

In tutto, lascia

  • return_typeessere il tipo di oggetto / primitivo / ecc. vorresti tornare (comunemente void)
  • blockName essere il nome della variabile del blocco che stai creando
  • var_typeessere il tipo oggetto / primitivo / ecc. si desidera passare come argomento (lasciare vuoto per nessun parametro)
  • varName essere il nome della variabile del parametro dato

E ricorda che puoi creare tutti i parametri che desideri.

Blocchi come variabili

Forse il più comune per dichiarazione.

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

Blocchi come proprietà

Un po 'come dichiarare i blocchi come variabili, anche se leggermente differenti.

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

Blocchi come parametri

Notare che questo è diverso da "Blocchi come argomenti"; in questo caso, stai dichiarando un metodo che vuole un argomento di blocco.

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

Blocchi come argomenti

Notare che questo è diverso da "Blocchi come parametri"; in questo caso, stai chiamando un metodo che vuole un argomento di blocco con un blocco anonimo. Se hai già dichiarato una variabile di blocco, è sufficiente passare il nome della variabile come argomento.

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

Blocco anonimo

Questo è funzionalmente un blocco anonimo, tuttavia la sintassi per assegnare blocchi alle variabili è semplicemente quella di impostare la variabile uguale a un blocco anonimo.

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

typedef Bloccare

Ciò consente di impostare un nome breve a cui è possibile fare riferimento proprio come qualsiasi altro nome di classe durante la dichiarazione dei blocchi.

typedef return_type (^blockName)(var_type);

Per un utilizzo successivo blockName posto della sintassi di dichiarazione di blocco standard, è sufficiente sostituire.

Blocco in linea

Questo è probabilmente un utilizzo meno utile dei blocchi, ma può comunque avere il suo posto. Un blocco inline è un blocco anonimo chiamato immediatamente dopo l'istanza.

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

I blocchi inline sono utili principalmente per l'offset dell'ambito e sono più o meno equivalenti a semplici blocchi di codice delimitati da parentesi graffe.

{
   //...
}

Blocchi ricorsivi

Ciò consente di chiamare un blocco da se stesso, creando un loop che può essere utilizzato durante i callback e le chiamate GCD. Questo metodo di creazione di istanze è privo di cicli di ritenzione in ARC.

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

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

Restituzione di blocchi

Un metodo può restituire un blocco,

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

come può una funzione, anche se un po 'strana.

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

Addendum

Se mi sono perso qualcosa, fatemelo sapere nei commenti e li ricercherò / aggiungerò.

Oh, e in Swift ...

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

È quasi come se fosse una caratteristica del linguaggio.


1
@pcperini Un ottimo elenco! E come utilizzare la definizione di blocco typedef nella dichiarazione di variabili (primo elemento nell'elenco)? La logica BlockType ^blockVar = Anonymous Blockmostra un errore di sintassi, anche senza ^ :(
esp

14
In qualche modo il mio cervello è incapace di ricordare tutte queste varie sintassi per le dichiarazioni di blocco. Probabilmente guardo questa risposta una volta alla settimana. Vorrei poterti dare 10 voti positivi per questo.
Ben Baron

36
Abbiamo bisogno di una StackOverflow Hall of Fame per risposte come questa.
bejonbee

1
L'ho convertito in Markdown per l'uso con un visualizzatore per la stampa. Maneggevole! gist.github.com/swizzlr/6268955
Swizzlr

20
Penso di averne bisogno come tatuaggio.
Isaac Overacker


39

Typedef:

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

In linea:

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

Metodo:

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

Questa risposta mostra che dopotutto non è così complicato ... solo 3 diverse sintassi da combinare e abbinare.
Joseph Chen

4
La risposta accettata è solo una copia di questa risposta con gonfiore inutile.
Erik Aigner

16

La libreria di frammenti di Xcode 4 contiene modelli per i typedef di blocco e i blocchi inline come variabili. Sono disponibili anche tramite completamento automatico ( typedefblocke inlineblock).

Per i blocchi come argomenti dei metodi, consiglierei di dichiarare a typedefe quindi di usarlo semplicemente. Rende il codice molto più facile da leggere.


11

Ho scritto un completamentoBlock per una classe che restituirà i valori di un dado dopo che sono stati agitati:

  1. Definisci typedef con returnType ( dichiarazione .hsopra @interface)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
  2. Definisci una @propertyper il blocco ( .h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
  3. Definisci un metodo con finishBlock( .h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
  4. Inserire il metodo definito in precedenza nel .mfile e eseguire il commit finishBlocksu @propertydefinito in precedenza

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
    
  5. Per attivare completionBlockpassare il valore di variabile predefinito ad esso (non dimenticare di controllare se completionBlockesiste)

    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;

Sarebbe bello descrivere l'intero processo passo dopo passo, i blocchi sono difficili da capire se sei nuovo in ios ...
Alex Cio

3

Se hai bisogno di lavorare di nuovo in Xcode 4.2, puoi anche @synthesize un blocco dichiarato come una proprietà proprio come faresti con una proprietà non block. Non lasciarti scoraggiare dalla sintassi del blocco.

Se la tua proprietà di blocco è questa:

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

Quindi la tua @synthesize è questa:

@property blockName;

Saluti.


Ciao, potresti ricontrollare .. stavo solo cercando di seguirti .. @property blockNamenon funziona. Penso che dovrebbe essere @synthesize blockName;? (per sintetizzare un blocco)
jeet.chanchawat

oops ... ti aspetto già (indirettamente) menzionato che non funzionerà con xcode 7.
jeet.chanchawat
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.