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。