-
首先block 是一个匿名函数
-
block 有捕获外部变量的能力
-
block 声明的时候是使用 copy 还是 strong
-
block的类型有哪些
-
如何解决 block 的循环引用问题(只能使用 __weak 吗)
-
为什么使用__block 可以在 block 内修改外部变量的值
-
使用 clang 查看 block 内部实现
1. block 是一个匿名函数,我们就要从其语法定义说起(show the code)
- c函数(void返回值、funName 函数名、int a 参数、{printf(%d\n,a)函数表达式})
void funcName(int a) { printf("%d\n", a); };
- block(^脱字符、int 返回值、void 参数、{return 3;};表达式)
^int (void){ return 3; };
- block使用我们可以看出右边的 block 块是有参数无返回值类型
typedef void(^cycleBlockTest)(Block1ViewController *); @property(nonatomic,copy) cycleBlockTest testBlock; self.testBlock = ^ (Block1ViewController *vc){ [vc doSomeThing]; }; self.testBlock(self);
-
由以上对比可以看出c 函数和 block 匿名函数的区别,以及为什么我们把 block 叫匿名函数。
2、为什么说 block 有捕获外部变量的能力(show the code)
int a = 10;
void (^block)() = ^{
DebugLog(@"a = %d",a);
};
a++;
block();
DebugLog(@"a = %d",a);
- 输出结果分别是:10,11。这是为什么呢?这就是 block 的捕获外部变量的能力。那么 block 是如何捕获的呢,请在本文最后查看如何使用 clang 命令查看 block 内部实现,这里会讲述 block 是如何捕获外部变量。
3、block 在其声明的时候当在 MRC 的环境中使用 copy,当在 ARC 的环境中可使用 copy 也可以使用 strong。目前在 ARC 环境中我们一直还在使用 copy 的原因是延续了 MRC 时代的写法。
4、block 类型我们可以从两方面来说:一、内存分布上;二、声明上。
内存分布上
__NSGlobalBlock 全局 block
void(^block)() = ^{
DebugLog(@"block");
};
block();
DebugLog(@"%@",block);
block
Block1ViewController.m:60
<__NSGlobalBlock__: 0x10089c110>
__NSStackBlock 栈 block
int a = 10;
void(^block)() = ^{
DebugLog(@"block-%d",a);
};
block();
DebugLog(@"%@",^{
DebugLog(@"block-%d",a);
});
Block1ViewController.m:62
<__NSStackBlock__: 0x16cf8ba20>
__NSMallocBlock 堆 block
int a = 10;
void(^block)() = ^{
DebugLog(@"block-%d",a);
};
block();
DebugLog(@"%@",block);
block-10
Block1ViewController.m:59
<__NSMallocBlock__: 0x283394ae0>
block声明上
无参数无返回值 void(^block)()
有参数无返回值 void(^block)(int a)
无参数有返回值 int(^block)()
有参数有返回值 int(^block)(int a,int b)
5、如何解决 block 的循环问题(有三种方法show the code)
1、 __weak __strong
__weak typeof(self)weakSelf = self;
self.testBlock = ^{
__strong typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomeThing];
};
self.testBlock();
2、__block
__block Block1ViewController *vc = self;
self.testBlock = ^{
[vc doSomeThing];
vc = nil;
};
self.testBlock();
3、self 作为参数
self.testBlock = ^(Block1ViewController *vc){
[vc doSomeThing];
};
self.testBlock(self);
网友评论