6

我知道__block块的标量变量需要存储类型才能看到对它们的更新,但是对象什么时候需要它?我认为__weak应该在捕获要在块内使用的自引用时使用,但我不知道什么时候需要实际使用__block普通对象的存储类型。

4

2 回答 2

16

__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

于 2013-07-24T05:51:01.067 回答
0

它们用于函数级变量。这些在块(和封闭范围)内是可变的,并且如果任何引用块被复制到堆中,它们就会被保留。使用存储修饰符声明的封闭词法范围的局部变量__block由引用提供,因此是可变的。任何更改都反映在封闭词法范围中,包括在同一封闭词法范围内定义的任何其他块。

__block变量存在于变量的词法范围和在变量的词法范围内声明或创建的所有块和块副本之间共享的存储中。因此,如果在帧中声明的块的任何副本在帧结束后仍然存在(例如,通过在某处排队以供稍后执行),则存储将在堆栈帧的破坏中幸存下来。因此,当您需要修改块内的对象或在销毁堆栈帧后需要对象时使用它们。

于 2013-07-24T00:31:34.857 回答