2017-03-07 39 views
3

我有一个关于声明块作为变量的最佳做法的问题。将Objective-C块声明为变量的最佳做法

最初我写了这样的我块变量:

id actionHandler = ^(UIAlertAction * action) { 
    // Handling code 
}; 

供以后使用像这样:

UIAlertAction *action = [UIAlertAction actionWithTitle:@"Title" 
               style:UIAlertActionStyleDefault 
               handler:actionHandler]; 

但是,当我遇到Apple's Working With Blocks指导来了,我看见我可以重写它像这样:

void (^actionHandler)(UIAlertAction * action) = ^(UIAlertAction * action) { 
    // Handling code 
}; 

这是“正确的”方式来声明它吗?这在我看来并不可读,但我对Objective-C没有太多的经验。那么将块声明为变量的最佳做法是什么?


编辑:好了,感谢所有的澄清!定义typedefshownamin-negm-awad和其他似乎也是一种很好的替代方法。

+1

你也可以考虑使用'typedef'。参见例如http://stackoverflow.com/questions/8956921/setting-up-a-block-property-in-custom-class/8956967#8956967 –

回答

2

没有一个一劳永逸这里回答:当你声明你的块变量作为id你不能再拥有的编译时间与你的块相关的信息,所以称其为手动成了问题:

id myHandler = ^(NSString *str) { 
    NSLog(@"%@", str); 
}; 
// Error: Called object type id is not a function or function pointer 
myHandler(@"Hello"); 

如果你想直接调用你的代码块,你需要将它重新转换为块。另一方面,如果仅声明块变量,以便可以将它传递给以块为参数的函数,则使用id可提供更易读的方法。

3

附加我想问一个修辞问题由dasblinkenlicht提到的问题:

可能你知道你可以替换此代码...:

NSString *string = @"All about types"; 

...与此代码:

id string = @"All about types"; 

你愿意吗?我相信,你没有。

那么为什么要把var的“typed”版本改成id版本呢?唯一的原因是,块类型的语法不方便,也不容易阅读(并且不容易编写)。我总是定义一个具体类型摆脱不方便语法:

typedef void (^ActionHandlerType)(UIAlertAction * action); 

然后:

ActionHandlerType actionHandler = ^(UIAlertAction * action) { 
    // Handling code 
}; 

为了说清楚:id是伟大的使用Objective-C的消息传递的动态特性。但是阻止执行不是迟到的。块的参数也不能改变它的数量或类型,所以没有什么可以动态绑定的。这是一个固定数量的参数的简单调用,固定类型。因此,使用id作为块的对象性质的副作用是可能的。但这不是一个用途,这是意图。

顺便说一句:如果您在参数列表中使用具体类型,Xcode可以自动完成参数的语法。用id这是不可能的。明显。

1

如果在此上下文中使用id,编译器将不会检查您声明的块的类型是否与该方法需要的块的类型相匹配。如果你不小心把块弄错了,很难调试,当方法尝试使用块时,事情可能会发生...

所以,如果你从来没有犯错误去id,但如果像我一样,你提供正确的类型,以便编译器可以帮助您解决问题。

为了更方便,因此不易出错,使用typedef,例如:

typedef void (^AlertActionHandler)(UIAlertAction * action); 
... 

AlertActionHandler actionHandler = ^(UIAlertAction * action) { ... 
相关问题