Objective C(および実際にはC、私が推測する)のブロック構文は、悪名高いほど不整合です。ブロックを引数として渡すことは、ブロックをivarとして宣言することとは異なります。これは、typedef
ingブロックとは異なります。
すぐに参照できるように手元に置いておくことができるブロック宣言構文の包括的なリストはありますか?
全体を通して
return_type
はオブジェクト/プリミティブ/などのタイプです。返したい(通常void
)blockName
は、作成しているブロックの変数名ですvar_type
は、object/primitive/etcなどのタイプです。引数として渡したい(パラメーターがない場合は空白のままにする)varName
は、指定されたパラメーターの変数名ですまた、必要な数のパラメーターを作成できることを忘れないでください。
おそらく最も一般的な宣言です。
return_type (^blockName)(var_type) = ^return_type (var_type varName)
{
// ...
};
ブロックを変数として宣言するのと似ていますが、微妙に異なります。
@property (copy) return_type (^blockName) (var_type);
これは「引数としてのブロック」とは異なることに注意してください。この例では、ブロック引数が必要なメソッドを宣言しています。
- (void)yourMethod:(return_type (^)(var_type))blockName;
これは「パラメーターとしてのブロック」とは異なることに注意してください。この例では、匿名ブロックでブロック引数を必要とするメソッドを呼び出しています。既にブロック変数を宣言している場合は、変数名を引数として渡すだけで十分です。
[someObject doSomethingWithBlock: ^return_type (var_type varName)
{
//...
}];
これは機能的には匿名ブロックですが、ブロックを変数に割り当てるための構文は、変数を匿名ブロックに等しく設定するだけです。
^return_type (var_type varName)
{
//...
};
typedef
ブロックこれにより、ブロックの宣言中に他のクラス名と同様に参照できる短い名前を設定できます。
typedef return_type (^blockName)(var_type);
その後、標準のブロック宣言構文の代わりにblockName
を使用するには、単に置き換えます。
これは間違いなくブロックの有用性は低いですが、それでもその場所があるかもしれません。インラインブロックは、インスタンス化の直後に呼び出される匿名ブロックです。
^return_type (var_type varName)
{
//...
}(var);
インラインブロックは、主にスコープのオフセットに役立ち、ブレースで区切られた単純なコードチャンクとほぼ同等です。
{
//...
}
これにより、それ自体からブロックを呼び出して、コールバックおよびGCD呼び出し中に使用できるループを作成できます。このインスタンス化方法には、ARCの保持サイクルがありません。
__block return_type (^blockName)(var_type) = [^return_type (var_type varName)
{
if (returnCondition)
{
blockName = nil;
return;
}
// ...
} copy];
blockName(varValue);
メソッドはブロックを返すことができますが、
- (return_type(^)(var_type))methodName
{
// ...
}
少し奇妙な場合、関数も同様です。
return_type (^FunctionName())(var_type)
{
// ...
}
何か見落とした場合は、コメントでお知らせください。調査/追加します。
blockName = (varName: var_type) -> (return_type)
言語機能のようです。
私は個人的にこのウェブサイトを使用するのが好きです( http://fuckingblocksyntax.com )。名前は、ブロック構文自体よりも覚えやすいです。
間違った単語を含むURLをロードできない場合は、このミラーを使用できます。 http://goshdarnblocksyntax.com
Typedef:
typedef void (^block)(NSString *arg);
列をなして:
void (^block)(NSString *) = ^(NSString *param) {
// do something....
};
方法:
- (void)method:(void (^)(NSString *param))handler
Xcode 4スニペットライブラリには、変数としてブロックタイプ定義とインラインブロックのテンプレートが含まれています。また、オートコンプリート(typedefblock
およびinlineblock
)を介して利用できます。
メソッドの引数としてのブロックについては、typedef
を宣言してから、単純にそれを使用することをお勧めします。これにより、コードがはるかに読みやすくなります。
振った後にサイコロの値を返すクラスのcompletionBlockを作成しました。
ReturnTypeでtypedefを定義します(.h
は@interface
宣言の上)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
ブロックの@property
を定義します(.h
)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
finishBlock
(.h
)でメソッドを定義します
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
前に定義したメソッドを.m
ファイルに挿入し、finishBlock
を前に定義した@property
にコミットします
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
completionBlock
をトリガーするには、定義済みのvariableTypeを渡します(completionBlock
が存在するかどうかを確認することを忘れないでください)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
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;
Xcode 4.2に戻って作業する必要がある場合は、非ブロックプロパティの場合と同様に、プロパティとして宣言されたブロックを@synthesizeすることもできます。ブロック構文にあなたを投げさせないでください。
ブロックプロパティがこれである場合:
@property (copy) return_type (^blockName) (var_type);
あなたの@synthesizeはこれです:
@property blockName;
乾杯。