Block是將函數(shù)及其執(zhí)行上下文封裝起來(lái)的對(duì)象
變量截獲
局部變量截獲 是值截獲
NSInteger num = 3;
NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
return n*num;
};
num = 1;
NSLog(@"%zd",block(2));
// 輸出是6而不是2,原因就是對(duì)局部變量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.因?yàn)閎lock內(nèi)部會(huì)截獲arr,且引用修飾符相同。
?
局部靜態(tài)變量截獲 是指針截獲
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,也是有效的。
?
全局變量,靜態(tài)全局變量截獲:不截獲,直接取值。
static NSInteger num3 = 300;
NSInteger num4 = 3000;
- (void)blockTest {
void(^block)(void) = ^{
NSLog(@"%zd",num3);//全局變量
NSLog(@"%zd",num4);//全局靜態(tài)變量
};
block();
}
// 300, 3000
Block循環(huán)引用
當(dāng)self持有Block,Block中又使用self時(shí),就會(huì)產(chǎn)生循環(huán)引用。
解決辦法:
- __weak來(lái)修飾self。當(dāng)self有可能被釋放時(shí),可以在block內(nèi)部再用__strong生成strongSelf;
__weak typeof(self) weakSelf = self;
self.setAlertBlock = ^(NSString *status) {
__strong typeof(weakSelf) strongSelf = weakSelf;
};
- 在block內(nèi)部使用完self后,將其置為nil,但這種方式有個(gè)問(wèn)題,如果block一直不被調(diào)用,那么循環(huán)引用將一直存在。所以,我們最好還是用__weak來(lái)修飾self。