4

这对我来说似乎是一种非常奇怪的交互,但同时它不仅有效,而且在此过程中不会引发任何警告或错误。只是希望更好地理解块,以及为什么这样的事情可能是对的或错的。

有什么理由不应该做这样的事情吗?

NSArray *array = [NSArray arrayWithObjects:^{NSLog(@"Block 1");}, ^{NSLog(@"Block 2");}, ^{NSLog(@"Block 3");}, nil];

for (id block in array) {
    [block invoke];
}
4

3 回答 3

4

将 Blocks 放入NSArrays 就可以了;他们是对象。事实上,它们继承自NSObject.

但是,您确实需要复制它们。这些块是在堆栈上创建的,需要移动到堆中才能超过当前方法的末尾。如果您使用的是 ARC,这很容易:

NSArray *array = [NSArray arrayWithObjects:[^{NSLog(@"Block 1");} copy], ...

在 MRR 下,您需要平衡它copy,因此您有两个不愉快的选择:使用临时数组,或者在创建数组后立即枚举数组并发release送给它的所有成员。

invoke另一方面,发送并不完全符合犹太教规,因为这是一种私有方法。调用 Block 的唯一完全符合 API 的方法是使用函数调用语法:

typedef GenericBlock dispatch_block_t;
for( GenericBlock block in array ){
    block();
}
于 2012-07-26T19:46:45.193 回答
1

当然,那很好。为什么会不好?

在像 JavaScript 这样的语言中,这种技术在注册事件处理程序时很常见。

object.clickHandlers.push(function() { doStuff() });
object.clickHandlers.push(function() { doMoreStuff() });

我认为没有理由不能将类似的技术用于 ObjC 块,因为它们是真实的对象。

不过,对我来说更有趣的问题是,无论您的目标是什么,这种模式是否是最佳选择。你还没有真正告诉我们。

于 2012-07-26T19:46:55.737 回答
1

Objective-C 中的块是“一等公民”对象。无论您可以对常规对象做什么,无论是作为参数传递、存储在数组还是字典中等等,您也可以对对象进行阻塞。

例如,一个块对象数组可能有助于对编译时未知的一系列动作进行编码;以字符串为键的块对象字典在实现脚本语言等方面可能很有用。

调用从集合中检索的块的最佳方法是将其转换为适当的类型,并在其上使用常规块调用语法。

于 2012-07-26T19:47:11.770 回答