Block是将函数及其执行上下文封装起来的对象
变量截获
局部变量截获 是值截获
NSInteger num = 3;
NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
return n*num;
};
num = 1;
NSLog(@"%zd",block(2));
// 输出是6而不是2,原因就是对局部变量num的截获是值截获。
NSMutableArray * arr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
void(^block)(void) = ^{
NSLog(@"%@",arr);//局部变量
[arr addObject:@"4"];
};
[arr addObject:@"3"];
arr = nil;
block();
// 打印为1,2,3.因为block内部会截获arr,且引用修饰符相同。
〜
局部静态变量截获 是指针截获
static NSInteger num = 3;
NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
return n*num;
};
num = 1;
NSLog(@"%zd",block(2));
// 输出为2,意味着num = 1这里的修改num值是有效的,即是指针截获。
// 同样,在block里去修改变量m,也是有效的。
〜
全局变量,静态全局变量截获:不截获,直接取值。
static NSInteger num3 = 300;
NSInteger num4 = 3000;
- (void)blockTest {
void(^block)(void) = ^{
NSLog(@"%zd",num3);//全局变量
NSLog(@"%zd",num4);//全局静态变量
};
block();
}
// 300, 3000
Block循环引用
当self持有Block,Block中又使用self时,就会产生循环引用。
解决办法:
- __weak来修饰self。当self有可能被释放时,可以在block内部再用__strong生成strongSelf;
__weak typeof(self) weakSelf = self;
self.setAlertBlock = ^(NSString *status) {
__strong typeof(weakSelf) strongSelf = weakSelf;
};
- 在block内部使用完self后,将其置为nil,但这种方式有个问题,如果block一直不被调用,那么循环引用将一直存在。所以,我们最好还是用__weak来修饰self。
网友评论