- Block介绍
- 截获变量
- __block修饰符
- Block的内存管理
- Block的循环引用
什么是Block?
- Block是将函数及其执行上下文封装起来的对象。
源码解析
- 使用 [clang -rewrite-objc file.m]查看编译之后的内容
什么是Block的调用?
- (即函数调用)
{
int multiplier = 6;
int(^Block)(int) = ^int(int num){
return num*multiplier;
};
Block(2);
}
截获变量
{
int multiplier = 6;
int(^Block)(int) = ^int(int num){
return num*multiplier;
};
multiplier = 4;
NSLog(@"result is %d",Block(2));
}
// =>result是12.
- 局部变量(基本数据类型,对象类型)
- 静态局部变量
- 全局变量
- 静态全局变量
- 对于基本数据类型的局部变量截获其值
- 对于对象类型的局部变量连同所有权修饰符一起截获
- 以指针形式截获局部静态变量
- 不截获全部变量、静态全局变量
源码解析
- 使用 [clang -rewrite-objc -fobjc-arc file.m]命令查看
__block修饰符
一般情况下,对被截获变量进行赋值操作需添加__block修饰符
笔试题的坑
- 上图无需添加__block
- 上图需添加__block
对变量进行赋值时
__block相关的笔试题
__block修饰的变量变成了对象
- 栈上的_forwarding指针指向自己。
__forwarding指针是用来干什么的?
Block的内存管理
-
impl.isa = &_NSConcreteStackBlock;
-
_NSConcreteGlobalBlock
-
_NSConcreteStackBlock
-
_NSConcreteMallocBlock
Block的Copy操作
栈上Block的销毁
栈上Block的Copy操作
栈上__block变量的Copy
__forwarding总结
{
__block int multiplier = 10;
_blk = ^int(int num){
return num*multiplier;
}
multiplier = 6;
[self executeBlock];
}
- (void)executeBlock
{
int result = _blk(4);
NSLog(@"result is %d",result);
}
// 输出结果result是24;
__forwarding存在的意义
- 不论在任何位置,都可以顺利的访问同一个__block变量。
Block的循环引用
{
_array = [NSMutableArray arrayWithObject:@"block"];
_strBlk = ^NSString *(NSString* num){
return [NSString stringWithFormat:@"halloc_%@",_array[0]];
};
_strBlk(@"hello");
}
解决循环引用
{
_array = [NSMutableArray arrayWithObject:@"block"];
__weak NSArray* weakArray = _array;
_strBlk = ^NSString *(NSString* num){
return [NSString stringWithFormat:@"halloc_%@",weakArray[0]];
};
_strBlk(@"hello");
}
{
__block MCBlock* blockSelf = self;
_blk = ^int (int num){
// var = 2
return num * blockSelf*var;
};
_blk(3);
}
这段代码的有问题吗?
- 在MRC下,不会产生循环引用。
- 在ARC下,会产生循环引用,引起内存泄漏。
{
__block MCBlock* blockSelf = self;
_blk = ^int (int num){
// var = 2
int result = num * blockSelf*var;
blockSelf = nil;
return result;
};
_blk(3);
}
- 如果block不调用,对象持有一直存在,循环引用一致存在。
Block总结
- 什么是Block?
- 为什么Block会产生循环引用?
- 怎样理解Block截获变量的特性?
- 你都遇到过哪些循环引用?你又是怎样解决的?