1.定義
- Block是OC中的一種數(shù)據(jù)類型,在iOS開發(fā)中被廣泛使用偎痛,是用來保存一段代碼
- ^是Block的特有標(biāo)志
- Block的實現(xiàn)代碼包含在{}之間
- 大多情況下旱捧,以內(nèi)聯(lián)inline函數(shù)的方式被定義和使用
- Block與C語言的函數(shù)指針有些相似,但使用起來更加靈活
5.1) 可以保存代碼
5.2) 有返回值
5.3) 有形參
block的定義方式:
先寫^,然后寫返回值類型踩麦,接著是參數(shù)類型枚赡,參數(shù)名,然后是大括號谓谦,分號贫橙,大括號里面的代碼
//定義block
//返回值可以自己推斷出來是什么類型的
^int(int x,int y){
return x + y
};
解釋:
^ : block的標(biāo)志:
第一個int:返回值類型;
int x: 第一個參數(shù)類型和參數(shù)名茁计;
int y:第二個參數(shù)類型和參數(shù)名料皇;
{}里面是我們想實現(xiàn)的某些功能,不能少了分號星压。
例如:
格式說明:
(返回類型)(^塊名稱)(參數(shù)類型) = ^(參數(shù)列表){
代碼實現(xiàn)
}践剂;
//如果沒有參數(shù),等號后面參數(shù)列表的()可以省略
#無返回值娜膘,無參數(shù)
void(^demoBlock)() = ^void(){
NSLog(@"hello world");
}();//在此加上小括號()就是block調(diào)用
或者
void(^demoBlock)() = ^{
NSLog(@"hello world");
};
#無返回值逊脯,有參數(shù)
void (^sumBlock) (int,int) = ^(int x,int y){
return x + y;
};
#有返回值,無參數(shù)
NSString(^demoBlock)() = ^NSString *(){
return @"hello world";
};
#有返回值竣贪,有參數(shù)
int(^demoBlock)(int x,int y) = ^int(){
return x * y;
};
2.常見相關(guān)面試題
block可以使用在定義之前聲明的局部變量:
int i = 10;
void(^myBlock)() = ^{
NSLog(@"%d",i);
};
i = 100;//實際上并沒有效果
myBlock();
#輸出結(jié)果為:10
注意:
(1) 在定義Block時军洼,會在Block中建立當(dāng)前局部變量內(nèi)容的副本(拷貝)
(2) 后續(xù)再對該變量的數(shù)值進行修改,不會影響B(tài)lock中的數(shù)值
(3) 如果需要在block中保持局部變量的數(shù)值變化演怎,需要使用__block關(guān)鍵字
(4) 使用此關(guān)鍵字后匕争,同樣可以在Block中修改該變量的數(shù)值
3.當(dāng)做參數(shù)傳遞
Block可以被當(dāng)做參數(shù)直接傳遞:
NSArray *array = @[@"張三",@"李四",@"尼瑪",@"趙五"];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%d %@",(int)idx,obj);
if ([@"尼瑪" isEqualToString:obj]) {
*stop = YES;
}
}];
#說明:遍歷并NSLog()array中的內(nèi)容,當(dāng)obj為“尼瑪”時停止遍歷
4.使用局部變量
在被當(dāng)做參數(shù)傳遞時爷耀,Block同樣可以使用在定義之前聲明的局部變量:
int stopIndex = 1;
NSArray *arr = @[@"張三",@"李四",@"尼瑪",@"趙五"];
[arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"第%d項內(nèi)容是%@",(int)idx,obj);
if ([@"尼瑪" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
注意:默認情況下甘桑,Block外部的變量,在Block中是只讀的!
BOOL flog = NO;;
NSArray *ar = @[@"張三",@"李四",@"尼瑪",@"趙五"];
[ar enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([@"尼瑪" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
flog = YES; //編譯錯誤 爆紅了
}
}];
5.__block關(guān)鍵字
如果需要修改
Block之外的局部變量跑杭,需要使用這個關(guān)鍵字
__block BOOL flog = NO;
NSArray *ar = @[@"張三",@"李四",@"尼瑪",@"趙五"];
[ar enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([@"尼瑪" isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
flog = YES; //現(xiàn)在可以修改了C薄!5铝隆爹橱!
}
}];
提示:無需使用__block關(guān)鍵字,在塊代碼中可以修改成員變量的數(shù)值(比較少用)
6.傳遞對象
對象傳遞進Block的方式
NSString *stopName = @"尼瑪";
NSArray *nameArr = @[@"張三",@"李四",@"尼瑪",@"趙五"];
[nameArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"第%d項內(nèi)容是%@",(int)idx,obj);
if ([stopName isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
為保證Block中代碼正常運行窄做,在stopName的指針傳遞Block時愧驱,Block會自動對stopName的指針做強引用