1.定义
- Block是OC中的一种数据类型,在iOS开发中被广泛使用,是用来保存一段代码
- ^是Block的特有标志
- Block的实现代码包含在{}之间
- 大多情况下,以内联inline函数的方式被定义和使用
- Block与C语言的函数指针有些相似,但使用起来更加灵活
5.1) 可以保存代码
5.2) 有返回值
5.3) 有形参
block的定义方式:
先写^,然后写返回值类型,接着是参数类型,参数名,然后是大括号,分号,大括号里面的代码
//定义block
//返回值可以自己推断出来是什么类型的
^int(int x,int y){
return x + y
};
解释:
^ : block的标志:
第一个int:返回值类型;
int x: 第一个参数类型和参数名;
int y:第二个参数类型和参数名;
{}里面是我们想实现的某些功能,不能少了分号。
例如:
格式说明:
(返回类型)(^块名称)(参数类型) = ^(参数列表){
代码实现
};
//如果没有参数,等号后面参数列表的()可以省略
#无返回值,无参数
void(^demoBlock)() = ^void(){
NSLog(@"hello world");
}();//在此加上小括号()就是block调用
或者
void(^demoBlock)() = ^{
NSLog(@"hello world");
};
#无返回值,有参数
void (^sumBlock) (int,int) = ^(int x,int y){
return x + y;
};
#有返回值,无参数
NSString(^demoBlock)() = ^NSString *(){
return @"hello world";
};
#有返回值,有参数
int(^demoBlock)(int x,int y) = ^int(){
return x * y;
};
2.常见相关面试题
block可以使用在定义之前声明的局部变量:
int i = 10;
void(^myBlock)() = ^{
NSLog(@"%d",i);
};
i = 100;//实际上并没有效果
myBlock();
#输出结果为:10
注意:
(1) 在定义Block时,会在Block中建立当前局部变量内容的副本(拷贝)
(2) 后续再对该变量的数值进行修改,不会影响Block中的数值
(3) 如果需要在block中保持局部变量的数值变化,需要使用__block关键字
(4) 使用此关键字后,同样可以在Block中修改该变量的数值
3.当做参数传递
Block可以被当做参数直接传递:
NSArray *array = @[@"张三",@"李四",@"尼玛",@"赵五"];
[array enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%d %@",(int)idx,obj);
if ([@"尼玛" isEqualToString:obj]) {
*stop = YES;
}
}];
#说明:遍历并NSLog()array中的内容,当obj为“尼玛”时停止遍历
4.使用局部变量
在被当做参数传递时,Block同样可以使用在定义之前声明的局部变量:
int stopIndex = 1;
NSArray *arr = @[@"张三",@"李四",@"尼玛",@"赵五"];
[arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"第%d项内容是%@",(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关键字
如果需要修改
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; //现在可以修改了!!!!
}
}];
提示:无需使用__block关键字,在块代码中可以修改成员变量的数值(比较少用)
6.传递对象
对象传递进Block的方式
NSString *stopName = @"尼玛";
NSArray *nameArr = @[@"张三",@"李四",@"尼玛",@"赵五"];
[nameArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"第%d项内容是%@",(int)idx,obj);
if ([stopName isEqualToString:obj] || idx == stopIndex) {
*stop = YES;
}
}];
为保证Block中代码正常运行,在stopName的指针传递Block时,Block会自动对stopName的指针做强引用