试图了解块如何在objective-c中工作.阅读apple的文档时有下一个问题(链接)
以下是我们不应该使用块的示例:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: The block literal scope is the "for" loop.
}
}
Run Code Online (Sandbox Code Playgroud)
但是我们如何能够获得3个不同的块来打印"你好,0","你好,1"和"你好,2"?我尝试了很多不同的方法,但每次我得到"你好,2"三次.
一个块开始在堆栈上生命,因此块的生命周期只与声明它的范围一样长.
for()循环的主体 - {} s中循环的主体 - 本身就是一个范围.因此,您的代码将堆栈[块]上的内容引用到周围范围[语言数组]中的变量中.
您需要将块复制到堆以使其存活:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
blockArray[i] = [^{ printf("hello, %d\n", i); } copy];
}
}
Run Code Online (Sandbox Code Playgroud)
如果不使用ARC,您还需要-release在某些时候复制块.
您可能会发现这个博客帖子很方便(我在块公开后不久就写了它).这个进入了一些提示,技巧和陷阱.
等等 - 是的 - 你是对的.ARC编译器中存在着神奇的现象,导致块看起来神奇地堆在堆上.但是,我在LLVM文档中找不到明确记录此行为的任何内容.如果你关闭ARC,你会看到输出是2,2,2而不是0,1,2.
这有点新的行为.在有人能够在编译器中找到明确定义如何支持它的显式注释之前,我不会依赖此行为.
@autoreleasepool {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
void (^block)(void) = ^{ printf("hello, %d\n", i); };
NSLog(@"%p", block);
blockArray[i] = block;
NSLog(@"%p", blockArray[i]);
}
for (int i = 0; i < 3; ++i) blockArray[i]();
}
Run Code Online (Sandbox Code Playgroud)
输出:
2012-12-24 16:15:36.752 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.755 jkdfjkfdjkdfjk[70708:303] 0x100108160
2012-12-24 16:15:36.758 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.759 jkdfjkfdjkdfjk[70708:303] 0x100108000
2012-12-24 16:15:36.760 jkdfjkfdjkdfjk[70708:303] 0x7fff5fbff838
2012-12-24 16:15:36.760 jkdfjkfdjkdfjk[70708:303] 0x100102e70
hello, 0
hello, 1
hello, 2
Run Code Online (Sandbox Code Playgroud)
因此,在堆栈上创建块并在for()循环范围之外的赋值上自动复制到堆.
类似的测试还表明,当作为参数传递给NSArray的addObject:时,将复制该块.
| 归档时间: |
|
| 查看次数: |
2652 次 |
| 最近记录: |