何时在带有ARC的对象引用上使用__block关键字
何时在带有ARC的对象引用上使用__block关键字
这个问题已经有了答案:
我理解对于标量变量,__block
存储类型在块看到它们的更新时是必需的,但是,对象什么时候需要它?我相信,当捕获一个self引用供块内使用时应该使用__weak
,但我不知道何时需要实际使用__block
存储类型来处理普通对象。
如果你想要通过块内部的代码改变标量变量的值,那么__block
是必需的。捕获的标量在块内看起来像是const
,因此不能被改变。如果你有一个对象的指针,同样的规则适用 - 捕获的指针本身将是一个const
指针,因此不能被修改,但是它所指向的对象可以被块内部的代码修改。如果你想改变所指向的对象,则指针本身必须改变,因此该指针必须用__block
类型声明。永远不需要将对象本身声明为__block
,只需要将指向该对象的指针声明为__block
,并且仅在指针必须被更改时才需要声明。\n\n如果你有正确的心理模型,块就不那么混乱了。重要的是要知道,块最初分配在堆栈上,因此在堆栈帧弹出时,词法作用域被销毁,块也会消失。如果你希望块在创建它的词法作用域的生命周期之外活得更久,可使用Block_copy()
或发送它一个-copy
消息将其移动到堆中。当块被复制到堆中时,所有捕获的const
变量都跟着它来了,并且这些const
变量指向的任何对象都会被保留下来。当块从堆中移除时,被const
变量所指向的所有对象都将被释放。\n\n__block
变量在编译时“内部”有一个额外的间接层(你看不到),包含在块中,因此当块被复制到堆中时,捕获的__block
变量和这些不可见的指针也会被调整为指向这些__block
变量在堆中的新位置。这意味着__block
变量的地址可能会改变,因此如果你使用该地址,请小心。你也可以看到__block
变量在某种意义上“在”块的外部生存,因此这些变量可以从块外部的代码中读取和修改。\n\n我简要地提到了这些,但你可以在以下链接中找到更好的解释,它们按复杂性递增排列:\n\nhttp://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/\n\nhttp://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html\n\nhttp://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html