为了使块能够工作,它们必须保留局部变量,它们必须有权访问堆栈框架。
由于该框架必须在函数退出后仍然存在,所以我认为该块要处理的是原始堆栈框架的副本。
堆栈框架是否保留一个块或该块保留了堆栈框架?
队列是否保留其中的块?
答案 0 :(得分:2)
块不保留堆栈框架。由块引用的堆栈变量在堆栈上被引用,直到将块移到堆中为止。那时,所有自动变量都将与块一起复制,并且所有__block
变量都将复制到堆中。
有关详细信息,请参见块编程主题中的Blocks and Variables。
堆栈框架不会保留任何内容,也不会保留堆栈框架。堆栈帧无法“做”任何事情(它们只是偏移到堆栈中)。而且没有什么可保留的(它们只是偏移到堆栈中)。堆栈框架无法幸免于它们的作用域。
队列有效保留添加到队列中的块(并且块有效保留其队列直到执行)。 “有效地”我的意思是“有一个强有力的参考可以防止其被破坏”。这是否通过调用 objc_retain
来实现,这是实现细节。
编辑:最后一段可能比它所阐明的更加混乱。实际上,调用dispatch_async
会“复制”该块,而不是保留它。但是,此处的“复制”一词与其他对象的含义并不完全相同。这实际上是指将一个块从堆栈移动到堆,您的访问员可能正在探索MRC问题,即您没有保留要保留的块,而是将其复制。但是在ARC中,这已经悄悄地进行了,最好从强引用的角度来考虑它,这就是我希望提出的观点。当您调用dispatch_async时,它会自动为您复制该块,并在完成时释放该块(这是记录的行为;请参见链接;对于MRC和ARC都是如此)。因此,您无需维护对块的单独引用即可在块处于队列中时将其保留(这非常不方便)。
dispatch_queue_create中记录了在执行之前,块还保持对队列的引用。