OC目标 – Block-目标类型的auto变量
1. Block内部拜访了目标类型的auto变量
当block
内部拜访了目标类型的auto
变量时,此刻block或许在栈上
,也或许在堆上
,不同类型
的block所表现的动作是不一样的
1.1 根底代码
创立一个ZSXPerson
类,在- (void)dealloc
打印一下,这样咱们能够清楚看到ZSXPerson
目标什么时候毁掉
@interface ZSXPerson : NSObject
@end
@implementation ZSXPerson
- (void)dealloc {
[super dealloc];
NSLog(@"ZSXPerson --- %s", __func__);
}
@end
main.m
int main(int argc, const char * argv[]) {
@autoreleasepool {
{
ZSXPerson *person = [[ZSXPerson alloc] init];
}
NSLog(@"-----");
}
return 0;
}
在{}
内,初始化一个ZSXPerson
目标,然后在在{}
外打了断点
能够看到person
目标出了{}
会马上毁掉
接下来咱们在此根底上,测验不同 block 对person
目标毁掉时机的影响
1.2 Block拜访person目标
添加一个block,内部拜访person目标
ZSXBlock block;
{
ZSXPerson *person = [[ZSXPerson alloc] init];
person.age = 10;
block = ^ {
NSLog(@"%d", person.age);
};
}
NSLog(@"block - %@", [block class]);
NSLog(@"-----");
此刻断点停留在{}
之后,按理说 person 现已出了效果域了,但实践却没有毁掉
咱们断点持续往下走
出了@autoreleasepool
之后,person
才毁掉。这时候刚好 block 也现已出了效果域,block
是会毁掉的。因而,block
里面临person
有强引证,所以出了第一个{}
的时候,虽然person
现已走出效果域,可是此刻block
还在效果域内,它还持有person
,所以person
并不会开释
1.2.1 检查底层完成
block拜访目标类型的auto变量后
- block结构体中持有
person
成员的指针 -
__main_block_desc_0
结构体中多了copy
和dispose
两个函数。这两个函数是用来办理block
所持有变量的持有联系的
由于block里面持有了目标,目标自身在内存中是经过引证计数
来办理内存的,因而block也需要对其负责内存办理
1.3 NSStackBlock
类型block拜访目标类型
NSStackBlock
类型block自身就是随时或许开释的,所以NSStackBlock
类型的block没有必要强持有拜访目标
1.3.1 修正代码
代码中咱们不运用
strong变量接收block,这时候的block就是NSStackBlock
类型的
ZSXBlock block;
{
ZSXPerson *person = [[ZSXPerson alloc] init];
person.age = 10;
^ {
NSLog(@"%d", person.age);
};
}
NSLog(@"block - %@", [block class]);
NSLog(@"-----");
打印成果:
person
出了效果域马上就开释了,因而能够说明这时候的block
并没有持有person
。
2. 总结
当block
内部拜访了目标类型的auto
变量时
-
如果block是在
栈上
,将不会
对auto变量产生强引证 -
如果block被
拷贝到堆上
- 会调用block内部的
copy
函数 - copy函数内部会调用
_Block_object_assign
函数 - _Block_object_assign函数会根据auto变量的
修饰符
(__strong、__weak、__unsafe_unretained)做出相应
的操作,形成强引证
(retain)或者弱引证
- 会调用block内部的
-
如果block从堆上
移除
- 会调用block内部的
dispose
函数 - dispose函数内部会调用
_Block_object_dispose
函数 - _Block_object_dispose函数会
主动开释
引证的auto变量(release)
- 会调用block内部的
@oubijiexi