objective-c - 何时在 ARC 的对象引用上使用 __block 关键字

标签 objective-c automatic-ref-counting objective-c-blocks

<分区>

我知道标量变量需要 __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/

相关文章:

iphone - 我怎么能创建一个类似于这个的自定义标签栏

objective-c - 初始化器和复制

Objective-C ARC 属性重新声明混淆

objective-c - 如何在 Swift 中使用 enumerateObjectsUsingBlock

ios - 如何将事件处理程序 block 放在自定义类上

iphone - 用于身份验证的 Cocoa 设计模式

ios - 核心数据 : "Cannot delete object that was never inserted."

ios - 为 UIWebView 设置委托(delegate)

ios - 如何一次为很多文件添加 -fobjc-arc

ios - 印象笔记 session authenticateWithViewController :completionHandler: does not trigger completionHandler