目标C中的块语法(实际上是C,我认为)是众所周知的不协调。将块作为参数传递看起来与将块声明为ivars不同,后者看起来与typedef
块不同。
是否有一个完整的块声明语法列表,我可以随时查看以供快速参考?
答案 0 :(得分:692)
全程,让
return_type
是object / primitive / etc的类型。你想回来(通常void
)blockName
是您正在创建的块的变量名称var_type
是类型对象/ primitive / etc。你想作为一个参数传递(留空没有参数)varName
是给定参数的变量名称请记住,您可以根据需要创建任意数量的参数。
可能是宣言中最常见的。
return_type (^blockName)(var_type) = ^return_type (var_type varName)
{
// ...
};
就像将块声明为变量一样,但却略有不同。
@property (copy) return_type (^blockName) (var_type);
请注意,这与“Block as Arguments”不同;在这种情况下,您将声明一个需要块参数的方法。
- (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)
这几乎就像是一种语言功能。
答案 1 :(得分:80)
我个人喜欢使用这个网站(http://fuckingblocksyntax.com)。该名称比块语法本身更容易记住:
如果您无法在其中加载包含错误字词的网址,则可以使用此镜像:http://goshdarnblocksyntax.com
答案 2 :(得分:39)
的typedef:
typedef void (^block)(NSString *arg);
内联:
void (^block)(NSString *) = ^(NSString *param) {
// do something....
};
方法:
- (void)method:(void (^)(NSString *param))handler
答案 3 :(得分:16)
Xcode 4片段库包含块typedef和内联块作为变量的模板。它们也可以通过自动完成功能获得(typedefblock
和inlineblock
)。
对于作为方法参数的块,我建议声明typedef
,然后简单地使用它。它使代码更容易阅读。
答案 4 :(得分:11)
我为一个类写了一个completionBlock,它会在它们被震动后返回一个骰子的值:
使用returnType(.h
声明上方@interface
)定义typedef
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);
}
答案 5 :(得分:6)
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;
答案 6 :(得分:3)
如果您需要在Xcode 4.2中工作,您还可以@synthesize声明为属性的块,就像使用非块属性一样。不要让块语法抛弃你。
如果你的阻止属性是这样的:
@property (copy) return_type (^blockName) (var_type);
然后你的@synthesize是这样的:
@property blockName;
干杯。