block如果要訪問(wèn)block以外定義的變量镇饺,對(duì)基本數(shù)據(jù)類型的局部變量、靜態(tài)變量送讲、全局變量奸笤、全局靜態(tài)變量和對(duì)象變量的接受方式是不一樣的。
1哼鬓、局部變量截獲是值截獲监右。 比如:
NSInteger num = 3;
NSInteger(^block)(NSInteger) = ^NSInteger(NSInteger n){
return n*num;
};
num = 1;
NSLog(@"%zd",block(2));
這里的輸出是6而不是2,原因就是對(duì)局部變量num的截獲是值截獲异希。
同樣健盒,在block里如果修改變量num,也是無(wú)效的,甚至編譯器會(huì)報(bào)錯(cuò)扣癣。
NSMutableArray * arr = [NSMutableArray arrayWithObjects:@"1",@"2", nil];
void(^block)(void) = ^{
NSLog(@"%@",arr);//局部變量
[arr addObject:@"4"];
};
[arr addObject:@"3"];
arr = nil;
block();
打印為1惰帽,2,3
局部對(duì)象變量也是一樣父虑,截獲的是值该酗,而不是指針,在外部將其置為nil士嚎,對(duì)block沒(méi)有影響垂涯,而該對(duì)象調(diào)用方法會(huì)影響
2、對(duì)于靜態(tài)局部變量航邢,block生成的時(shí)候直接生產(chǎn)一個(gè)指向其地址的同名指針,看下面這個(gè)例子骄蝇。
-(void)test2{
//局部靜態(tài)變量膳殷,截獲指針
static inta =1;
int(^ccCallBack)(void) = ^{
int b = a +1;//這里的a 實(shí)際上是一個(gè)指向其外部哪個(gè)a的指針 ,就像這樣(*a+1)
returnb;
};
a =3;
intres = ccCallBack();
NSLog(@"result: %d",res);//4
}
3九火、全局變量赚窃,靜態(tài)全局變量截獲:對(duì)于全局變量和靜態(tài)全局變量,block直接訪問(wèn)其值岔激,而不進(jìn)行截獲勒极。也就是說(shuō),block執(zhí)行的時(shí)候虑鼎,改全局變量活靜態(tài)全局變量是什么值辱匿,就用什么值。
4炫彩、對(duì)于外部的對(duì)象變量匾七,block但截獲其指針,而且連同其所有權(quán)修飾符一起截獲江兢∽蛞洌看下面這個(gè)例子:
-(void)test5{
//對(duì)象類型,連同所有權(quán)修飾符一期截獲
//在不寫(xiě)所有權(quán)修飾符的時(shí)候,這個(gè)變量的修飾符默認(rèn)為_(kāi)_strong
id object = [NSObject new];//所以杉允,這個(gè)等同于 __strong id object = [NSObject new]
id(^ccCallBack)(void) = ^{
return object;//上面聲明的時(shí)候是 __strong 修飾符邑贴,那么這里訪問(wèn)的object的也是帶__strong修飾符的指針
};
id_object = ccCallBack();
NSLog(@"result: %@",_object);
}
一般情況下,如果我們要對(duì)block截獲的局部變量進(jìn)行賦值操作需添加__block
修飾符叔磷,而對(duì)全局變量拢驾,靜態(tài)變量是不需要添加__block修飾符的。
另外世澜,block里訪問(wèn)self或成員變量都會(huì)去截獲self独旷。
參考文章:https://blog.csdn.net/u012094456/article/details/102949678
https://blog.csdn.net/qq_34270183/article/details/105185200