<分区>
我知道标量变量需要 __block
存储类型才能让 block 看到它们的更新,但是对象什么时候需要它?我相信 __weak
应该在捕获要在 block 内使用的自引用时使用,但我看不到什么时候需要实际使用 __block
存储类型对于普通物体。
<分区>
我知道标量变量需要 __block
存储类型才能让 block 看到它们的更新,但是对象什么时候需要它?我相信 __weak
应该在捕获要在 block 内使用的自引用时使用,但我看不到什么时候需要实际使用 __block
存储类型对于普通物体。
最佳答案
如果您想使用 block 内的代码更改标量变量的值,则需要
__block
。捕获的标量在 block 内显示为 const
,因此无法更改。如果你有一个指向对象的指针,同样的区别适用——捕获的指针本身将是一个 const
指针,因此不能被修改,但是指向的对象可以被 block 内的代码修改.如果要更改指向的对象,则指针本身必须更改,因此必须使用 __block
类型声明指针。永远不需要将对象本身声明为 __block
,只需声明指向该对象的指针,并且仅在必须更改指针时才需要。
如果您有正确的心智模型, block 就不会那么困惑。重要的是要知道 block 最初是在堆栈上分配的,因此当弹出堆栈帧时词法作用域被销毁时 block 就会消失。如果您希望该 block 在创建该 block 的词法作用域的生命周期之后继续存在,请使用 Block_copy()
或向其发送 -copy
将其移动到堆中> 消息。将 block 复制到堆时,所有捕获的 const
变量都会一起复制,并且保留这些 const
变量指向的任何对象。当 block 从堆中移除时,const
变量指向的所有对象都将被释放。
__block
变量“在引擎盖下”有一个额外的间接层,编译器使用(并且你看不到)包含在 block 中,所以当 block 被复制到堆时,捕获的 __block
变量也是如此,不可见的指针被调整为指向这些 __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
关于objective-c - 何时在 ARC 的对象引用上使用 __block 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17823167/