【发布时间】:2014-11-05 19:22:48
【问题描述】:
通常块可以有 3 种类型:NSGlobalBlock、NSStackBlock、NSMallocBlock。举个例子:
void (^aBlock)(NSString *someString) = ^(NSString *someString){
NSLog(@"Block was executed. %@", someString);
};
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:aBlock forKey:@"aBlock"];
因为如果我执行 po dictionary aBlock 不会捕获周围的范围,我会得到 p>
aBlock = NSGlobalBlock:0x165dde60> 这是正确的
如果我那么做:
NSString *string = @"Test";
void (^aBlock)(NSString *someString) = ^(NSString *someString){
NSLog(@"Block was executed. %@ %@", someString, string);
};
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:aBlock forKey:@"aBlock"];
然后po字典,我得到:
aBlock = NSMallocBlock:0x165dde60> 这让我很困惑
这不应该是 NSStackBlock 并且只有在我这样做时才成为 NSMallocBlock:
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[aBlock copy] forKey:@"aBlock"];
我在使用 ARC 的 iOS 7.1 上,据我所知,块在向下传递堆栈时默认不应在 ARC 中复制,而应仅在向上传递堆栈时复制(从函数返回)。
我错过了什么?
【问题讨论】:
-
我不明白您如何能够将 stack 分配的内存添加到字典中。要使块持续存在,它需要在堆上。无论如何,我的猜测是,在这种情况下,
NSMallocBlock是在编译时确定的,因为编译器可以看到在堆栈框架之外需要它。 -
嗨,您对堆栈与堆的评论是有效的,我的困惑来自这样一个事实,即文档明确指出,即使在 ARC 下,当我们向字典中添加本地范围的块时,我们也必须复制它(基本上将它移动到堆中),在当前情况下,根据文档它不应该存在时,块已经在堆中。也许文档已经过时了,但是直到我确定某些事情之前,我才考虑使用 NSMapTable 并将其设置为复制其值。对我来说,这似乎是最安全的方法。
-
您可以编辑您的帖子以包含该信息吗?知道会很有帮助。 (特别是您引用的文档的链接)。我认为这不是您试图在本地范围之外保留的字典吗?
标签: objective-c memory-management automatic-ref-counting nsdictionary objective-c-blocks