Objective-C区块 [英] Objective-C blocks

查看:72
本文介绍了Objective-C区块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图了解目标C中的块是如何工作的.阅读苹果文档时遇到了下一个问题(链接)

Trying to understand how blocks working in objective-c. Got next question while reading apple's docs (link)

下面是一个示例,说明如何不使用块:

Here is an example how we should no use blocks:

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.
    }
}

但是我们如何获得3个不同的块,分别打印"hello,0","hello,1"和"hello,2"?我尝试了许多不同的方法,但是每次我都两次打招呼"两次.

But how we could get 3 different blocks that will print "hello, 0", "hello, 1" and "hello, 2"? I tried many different ways but every time I got "hello, 2" three times.

推荐答案

一个块开始在栈中生效,因此,该块的生存期仅与声明它的作用域一样长.

A block starts out life on the stack and, thus, a block's lifespan is only as long as the scope it is declared in.

for()循环的主体({} s中的循环主体)本身就是一个作用域.因此,您的代码会将对堆栈[块]上的内容的引用放到周围范围[语言数组]中的变量中.

The body of a for() loop -- the body of the loop in the {}s -- is a scope in and of itself. Thus, your code is putting a reference to something on the stack [the block] into a variable in the surrounding scope [the language array].

您需要将块复制到堆中才能生存:

You need to copy the block to the heap to have it survive:

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];
    }
}

如果不使用ARC,则有时还需要-release复制的块.

If not using ARC, you would also need to -release the copied blocks at some point.

您可能会发现方便的网志帖子(我在Blocks公开后不久写了它).这是一些技巧,窍门和陷阱 a>.

You might find this weblog post handy (I wrote it shortly after Blocks were made public). This one goes into a few tips, tricks, and gotchas.

等等-是的-你是正确的. ARC编译器中发生了不可思议的事情,这似乎使这些块似乎神奇地出现在了堆上.但是,在LLVM文档中找不到任何明确记录此行为的内容.如果关闭ARC,则会看到输出类似于2,2,2,而不是0,1,2.

Wait -- yeah -- you're correct. There is magic going on in the ARC compiler that is causing the blocks to seemingly be on the heap magically. However, I can't find anything in the LLVM documentation that explicitly documents this behavior. If you turn off ARC, you'll see the output be something like 2,2,2 instead of 0,1,2.

这是一种新的行为.在有人可以在编译器中找到明确说明该定义如何支持的明确注释之前,我不会依靠这种行为.

This is somewhat new behavior. I wouldn't rely on this behavior until someone can find the explicit note in the compiler that defines exactly how this is supported.

@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]();
}

输出:

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

因此,该块是在堆栈上创建的,并在for()循环范围之外的赋值下自动复制到堆中.

Thus, the block is created on the stack and copied to the heap automatically on the assignment outside of the scope of the for() loop.

类似的测试还显示,将块作为参数传递给NSArray的addObject:时将复制该块.

A similar test also reveals that the block will be copied when passed as an argument to NSArray's addObject:.

这篇关于Objective-C区块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆