参见英文答案 >
What does the “__block” keyword mean?8个
我知道块的标量变量需要__block存储类型才能看到它们的更新,但是何时需要对象?我相信在捕获要在块中使用的自引用时应该使用__weak,但是我不知道何时需要为普通对象实际使用__block存储类型.
我知道块的标量变量需要__block存储类型才能看到它们的更新,但是何时需要对象?我相信在捕获要在块中使用的自引用时应该使用__weak,但是我不知道何时需要为普通对象实际使用__block存储类型.
解决方法
如果要使用块内的代码更改其值,则标量变量需要__block.捕获的标量在块内显示为const,因此无法更改.如果你有一个指向对象的指针,则应用相同的区别 – 捕获的指针本身将是一个const指针,因此无法修改,但指向的对象可以通过块内的代码进行修改.如果要更改指向的对象,则指针本身必须更改,因此必须使用__block类型声明指针.永远不需要将对象本身声明为__block,而只需要指向对象的指针,并且只有在必须更改指针时才需要.
如果你有正确的心理模型,那么阻止就不那么令人困惑了.重要的是要知道块最初是在堆栈上分配的,因此在弹出堆栈帧时销毁词法范围时会消失.如果希望块在创建块的词法作用域的生命周期之前挂起,请使用Block_copy()将其移动到堆中,或者发送-copy消息.当块被复制到堆时,所有捕获的const变量都会继续,并且这些const变量指向的任何对象都会被保留.从堆中删除块时,将释放const变量指向的所有对象.
__block变量“引擎盖下”有一个额外的间接层,编译器使用(并且你看不到)块,所以当块被复制到堆时,捕获的__block变量和隐形也是如此调整指针以指向这些__block变量的新堆位置.这意味着__block变量的地址可以更改,因此如果使用该地址则要小心.您还可以看到__block变量在某种意义上存在于块外部,因此可以从块外部的代码读取和修改这些变量.
我一直很简短,但你可以在这里找到更好的解释,列出越来越复杂:
http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/
http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html