在ARC环境下面,编译器会根据一些情况自动把栈blcok copy到堆上面去。

ARC环境下,block只要被强指针指着,就会自动做copy操作。







auto变量本身是什么类型,被block捕获进去后就是什么类型。比如原来是int类型,捕获block里面去后,就是int类型。如果有static修饰,int类型被捕获进去后就是int *类型。
MJPerson *类型被捕获进去后就是MJPerson *类型。如果用static修饰了MJPerson *,被block捕获进去后就是MJPerson * *类型。



由上图得知,MRC环境下,堆空间的block会在block里面对person对象做一次retain操作,当block要销毁的时候,又会回来对person进行release操作。
由此得出一个结论,不管是MRC还是ARC,栈空间上面的block,是不会去拥有外面那些对象的,是不会去持有那些对象的,不能保住它的命,也就是不会强引用,堆空间的block,是有能力去保住外面对象的命的,换成ARC的说法就是强引用,但是MRC下是没有强引用这种说法的,只有reatin保住它的命,release释放掉它。但是当堆空间的block自己销毁的时候,也会对里面用到的person对象进行一次release操作。


strong 修饰符是oc对象的默认修饰符
id arr = [[NSArray alloc] init] 等同于 id __strong arr = [[NSArray alloc] init]






当初访问外面auto变量是以什么指针访问它,到时候它在block的结构体里面就是什么指针类型。但是如果block是栈block的话,不管auto变量指针是什么都没用。
如果block是在栈上,不管是MRC环境还是ARC环境,block内部都不会强引用外面的auto变量




图中的_block_object_assign函数的作用:这个函数(也就是这个操作),会自动根据block的结构体里面,*person是__strong类型的指针还是__weak类型的指针,对person对象产生强引用或者弱引用。也就是说执行完这个函数:block里面写的是__strong修饰的指针,那这个指针就会对外面的person对象产生强引用,如果是__weak修饰的指针,那这个指针对外面的person对象是弱引用。

这个函数里面做了:相当于对perosn进行一次release操作。也就是释放当初被block引用的那些变量。

总结:如果block是在栈空间的,不管外面访问的auto变量是强引用也好,还是弱引用也好,总之栈block都不会对它进行强引用,既都是弱引用。如果block是在堆空间的,那你是通过弱引用访问这个对象,还是通过强引用访问这个对象,效果就不一样了,如果强引用访问外面的auto变量,那block结构体里面生成的引用auto变量的指针也是强引用,所以block调用copy的时候,该指针会强引用外面的auto变量。反之要是weak就是弱引用。
如果是MRC环境,_block_object_assign函数就决定要不要对访问的外面的auto变量就行retain操作。不管是强引用还是弱引用_block_object_assign函数都会调用的。(只要block拷贝到堆上面,就会自动调用_block_object_assign函数)
补充:

此时person不会释放,因为person强持有testBlock,testBlock里面强持有person
不管是MRC环境还是ARC环境:属性block,先看block是什么类型,再看block属性用什么关键词修饰,才能决定block的最终的类型(block作为属性,strong效果和copy效果一样,都会对block进行拷贝操作,但是我们习惯于用copy,weak修饰block,block不会进行拷贝操作)。



网友评论