Block小结
一、block的类型
- GlobalBlock
- StackBlock
- MallocBlock
二、生成条件
GlobalBlcok:
如果一个block没有引用任何外部变量,此时block是一个GlobalBlock
StackBlock:
相对于GlobalBlock,如果一个block内部引用了外部变量
MRC:此时的block会是一个GlobalBlock
ARC:此时的block会是一个MallocBlock
Tips: ARC下会对GlobalBlock做优化,当创建一个block时会默认返回一个MallocBlock。但是在ARC中当block作为函数参数时,此时block是一个GlobalBlock。
MallocBlock:
MRC:对StackBlock copy得到MallocBlock
ARC:默认创建的Block,除了GlobalBlock都是MallocBlock
三、block的copy、retain、release操作
这些操作都是在MRC情况下
- 对block进行copy、retain、release都不会改变retainCount,retainCount始终是1
- GlobalBlock的retain、copy、release都无效
- StackBlock的retain、release操作无效,StackBlock在函数返回后,block内存将会被回收
- MallocBlock 支持retain、release,是retainCount始终是1
四、block对不同类型变量的存取
基本类型
局部变量,在block中只读。block__定义__时,copy变量的值,在block中作为常量使用;static变量、全部变量,在内存中的位置是固定的,block在读取时会直接从内存中读出,获取到最新的值;被__block修饰的变量,基本类型的block变量等效于static变量;block被另一个block使用时,另一个block被copy到堆上时,被使用的block也会被copy。但是作为参数的block是不会copy的引用类型
局变量和static变量在内存中的位置是确定的,所以不会retain变量,_instanceObj在block中使用时,不会retain _instanceObj本身,但是会retain self,local在block中 时,会retain对象,增加引用计数;block obj在block copy时也不会retain
附带几个block的坑,分析在MRC和在ARC情况下都是否能执行
题目1.
void exampleA()
{
char a = 'A';
^{
printf("%c\n",a);
}();
}
题目2.
void exampleB_addBlockToArray(NSMutableArray *array)
{
char b = 'B';
[array addObject:^{
printf("%c\n",b);
}];
}
void exampleB()
{
NSMutableArray *array = [NSMutableArray array];
exampleB_addBlockToArray(array);
void(^block)() = [array objectAtIndex:0];
block();
}
题目3.
void exampleC_addBlockToArray(NSMutableArray *array)
{
[array addObject:^{
printf("C\n");
}];
}
void exampleC()
{
NSMutableArray *array = [NSMutableArray array];
exampleC_addBlockToArray(array);
void(^block)() = [array objectAtIndex:0];
block();
}
题目4.
typedef void(^dBlock)();
dBlock exampleD_getBlock() {
chard = 'D';
return^{
printf("%c\n",d);
};
}
void exampleD()
{
exampleD_getBlock()();
}
题目5.
typedef void(^eBlock)();
eBlock exampleE_getBlock() {
chare = 'E';
void(^block)() = ^{
printf("%c\n",e);
};
returnblock;
}
void exampleE()
{
eBlock block = exampleE_getBlock();
block();
}
答案是:1、3 在MRC和ARC情况下都能使用 2、4、5 只有在ARC情况下才能使用
提示:stackBlock 会在block返回后被释放,global则不需要关系释放的问题,mallocBlock会手动释放或arc自动管理,在arc情况下,不作为参数的stackBlock会被自动创建为mallocBlock
文章参考:https://www.zybuluo.com/MicroCai/note/57603
http://blog.parse.com/learn/engineering/objective-c-blocks-quiz/