ios在字典或数组中存储^块?

时间:2012-10-24 04:50:04

标签: iphone objective-c ios objective-c-blocks

我可以将^块存储在字典或数组中吗?

我需要收听一个服务器通知,我需要提供一个块来处理通知,在我的项目中,几个视图控制器都希望听到通知,所以我做了一个通用的通知管理器,它有自己的块用于处理服务器通知,它有一个委托数组,所以在管理器的块中:

- (^)(NSString *message){
    for (delegate in allDelegates)
    {
        delegate.handlerBlock(message);
    }
}

但是我可以在一个集合中存储块吗?

3 个答案:

答案 0 :(得分:12)

您可以将对象存储到集合中。但要注意范围:当它们被排除在功能范围之外时复制它们。这是你的情况,因为你将它们存储在一个数组中。

[NSArray arrayWithObject: 
[[^{ NSLog(@"block 1"); } copy] autorelease],
[[^{ NSLog(@"block 2"); } copy] autorelease], nil]

在ARC上,你仍然需要告诉它你绝对需要复制你的块。它应该在释放数组时释放块。

  [NSArray arrayWithObject: 
    [^{ NSLog(@"block 1"); } copy],
    [^{ NSLog(@"block 2"); } copy], nil]

答案 1 :(得分:5)

块的特殊之处在于,在大多数情况下应该保留其他对象时应该复制它们。正如您现在必须阅读的那样,这是因为块从堆栈开始(“堆栈块”),并且仅在定义它们的本地范围内有效。复制堆栈块会为您提供堆块,并且像普通对象一样具有动态生命周期。复制堆块会简单地保留它,因此当你需要将块保持更长时间时,复制块总是正确的。

现在,带有块参数的函数通常负责根据需要复制块。因此,在将块传递给这些函数时,您不需要做任何特殊操作。但是,在这种情况下,您将块传递给[NSArray arrayWithObject:],它接受​​一个普通的对象参数。因为它不接受块参数,所以它不知道复制参数,所以它只会保留它。因此,当您将块传递给采用普通对象参数的方法时,您需要先将其复制。

答案 2 :(得分:1)

如果你阅读了非常好的文章here,你会发现如何做到这一点。并特别注意那里提到的“将它们从堆栈中复制出来”这个成语。