何时在ARC对象引用上使用__block关键字

chi*_*fet 6 objective-c objective-c-blocks automatic-ref-counting

我知道__block块的标量变量需要存储类型才能看到它们的更新,但是何时需要对象?我相信__weak应该在捕获要在块中使用的自引用时使用,但我不知道何时需要实际使用__block普通对象的存储类型.

Fre*_*red 15

__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