(转自https://github.com/oa414/objc-zen-book-cn 禅与 Objective-C 编程艺术 )
一些关键点:
block 是在栈上创建的
block 可以复制到堆上
Block会捕获栈上的变量(或指针),将其复制为自己私有的const(变量)。
(如果在Block中修改Block块外的)栈上的变量和指针,那么这些变量和指针必须用__block
关键字申明(译者注:否则就会跟上面的情况一样只是捕获他们的瞬时值)。
如果 block 没有在其他地方被保持,那么它会随着栈生存并且当栈帧(stack frame)返回的时候消失。仅存在于栈上时,block对对象访问的内存管理和生命周期没有任何影响。
如果 block 需要在栈帧返回的时候存在,它们需要明确地被复制到堆上,这样,block 会像其他 Cocoa 对象一样增加引用计数。当它们被复制的时候,它会带着它们的捕获作用域一起,retain 他们所有引用的对象。
如果一个 block引用了一个栈变量或指针,那么这个block初始化的时候会拥有这个变量或指针的const副本,所以(被捕获之后再在栈中改变这个变量或指针的值)是不起作用的。(译者注:所以这时候我们在block中对这种变量进行赋值会编译报错:Variable is not assignable(missing __block type specifier)
,因为他们是副本而且是const的.具体见下面的例程)。
当一个 block 被复制后,__block
声明的栈变量的引用被复制到了堆里,复制完成之后,无论是栈上的block还是刚刚产生在堆上的block(栈上block的副本)都会引用该变量在堆上的副本。
声明的变量和指针在 block 里面是作为显示操作真实值/对象的结构来对待的。
block 在 Objective-C 的 runtime(运行时) 里面被当作一等公民对待:他们有一个 isa
指针,一个类也是用 isa
指针在Objective-C 运行时来访问方法和存储数据的。在非 ARC 环境肯定会把它搞得很糟糕,并且悬挂指针会导致 crash。__block
仅仅对 block 内的变量起作用,它只是简单地告诉 block:
嗨,这个指针或者原始的类型依赖它们在的栈。请用一个栈上的新变量来引用它。我是说,请对它进行双重解引用,不要 retain 它。 谢谢,哥们。
如果在定义之后但是 block 没有被调用前,对象被释放了,那么 block 的执行会导致 crash。 __block
变量不会在 block 中被持有,最后... 指针、引用、解引用以及引用计数变得一团糟
网友评论