MRC中分为
* NSConcreteGlobalBlock 全局静态block,不会访问任何外部变量
* NSConcreteStackBlock 保存在栈上的block,函数返回时会被销毁,编译器自动管理(栈内存特点),在MRC模式下初始化之后的非全局静态block都是这种类型,所以需要说明的是,MRC模式下,对于block的引用应该用copy,这样该block就会转变成下面这种类型
* NSConcreteMallocBlock 保存在堆上的block,程序管理生命周期,引用计数为0时才会被销毁。MRC下的栈上block被copy时被copy到堆上,变为MallocBlock。
ARC中去掉了NSConcreteStackBlock,默认block即为NSConcreteMallocBlock。可能苹果觉得ARC的内存管理能力足够强大,释放足够及时,堆上内存如果释放及时,还是有很大优势的,毕竟空间和引用管理比较方便
block对外部变量的使用有一个capture机制,其实质是将其copy进相关struct中供block使用的,内部修改不会影响外部。
如果需要影响外部,则变量申明为_block关键字即可,这样内部对该变量的实用变成了指针引用。
以上说明适用于分配在栈上的变量,对于堆上的指针变量天生就能修改原值,但是需要注意:
* 防止循环引用
* 防止野指针
1. 防止循环引用可以用__weak关键字声明指针
2. 防止野指针可以在block内部对其指针引用技术+1,结束之后-1(MRC),或者可以在block内部使用__strong关键字声明指针指向外部用__weak声明的变量
对于第二点可能有同学说,我平时没这么声明也没问题啊,是的,这需要前提,外部函数所属的对象的生命周期比block要长,否则就会因为引用了野指针crash了
火车上不方便补代码,回头补上代码例子
网友评论