在上一篇提到block是带有自动变量(局部变量)的匿名函数,本文来看看block的语法定义
首先作如下约定:
returnType:返回值类型
blockName:block的名称
paraType:参数类型
paraName:参数名称
block的语法定义主要有以下几种:
1、标准的声明与定义
returnType (^blockName)(paraType) = ^returnType (paraType paraName){
/*block 内部代码*/
};
block(para);
2、返回值类型为void
void (^blockName)(paraType) = ^void (paraType paraName) {
/*block 内部代码*/
};
block(para);
可以简写如下:
void (^blockName)(paraType) = ^(paraType paraName) {
/*block 内部代码*/
};
block(para);
3、参数类型为void
returnType (^blockName)(void) = ^returnType (void) {
/*block 内部代码*/
};
block(para);
可以简写如下:
returnType (^blockName)(void) = ^returnType {
/*block 内部代码*/
};
block(para);
4、返回值和参数类型都为void
void (^blockName)(void) = ^void (void) {
/*block 内部代码*/
};
block(para);
可以简写如下:
void (^blockName)(void) = ^ {
/*block 内部代码*/
};
block(para);
5、block名称为空时
此时blockName为空,即匿名block
block的简化声明
1、利用typedef简化block的声明
typedef returnType (^blockName) (paraType)
例如通过typedef声明一个block后,直接在属性或者方法参数中使用该block
/*简化block的声明*/
typedef void (^clickBlock)(NSInteger index);
@interface ViewController ()
/*定义一个block的属性*/
@property (nonatomic,copy) clickBlock buttonClickBlock;
/*将block作为方法参数*/
- (void)viewDidSelected:(clickBlock) selected;
@end
block的用法
常见用法
1、局部声明一个block类型的变量
例如在一个方法的内部定义如下block并且调用这个block
void (^localBlock)(int number) = ^(int number){
NSLog("%d \n",number);
};
localBlockIn(23);
block返回值为void时进行省略
2、声明一个block类型的属性
@property (nonatomic,copy) clickBlock buttonClickBlock;
3、block作为方法定义的形参
- (void)viewDidSelected:(clickBlock) selected;
4、方法调用时,block作为实参
- (void)viewDidSelected:(clickBlock)selected {
self.buttonClickBlock = selected;
}
不常见用法
1、block作为内联使用,即匿名block被声明后立即调用
^returnType (paraType paraName) {
/*block 内部代码*/
}(para);
2、block递归使用
block内部调用自身,形成递归,递归是很多算法的基础;特别注意的是:由于block内部调用了自身,这里必须用__block避免循环调用
__block returnType (^blockName)(paraType) = [^returnType (paraType paraName) {
/*递归条件判断*/
if (returnCondition) {
blockName = nil;
return;
}
/*block 内部代码*/
/*递归调用*/
blockName(paraName);
} copy];
/*首次调用*/
blockName(varValue);
3、block作为返回值
方法的返回值是一个block,常用于一些“工厂模式”的方法中,形式如下:
- (returnType(^)(paraType))methodName {
return ^returnType(paraType paramName) {
// ...
};
}
常用的Masonry框架里面
- (MASConstraint * (^)(id))equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
链式编程:将block作为方法的返回值,并且返回值的类型为调用者本身,并将该方法以setter形式返回,实现连续调用,即为链式编程
设计一个链式语法的简易加法器,主要代码如下:
@interface CaculateObject : NSObject
/*属性变量*/
@property (nonatomic,assign) NSInteger result;
/*实例方法,返回是一个block,返回类型是调用者本身*/
- (CaculateObject *(^)(NSInteger number))add;
@end
/*方法的实现*/
@implementation CaculateObject
- (CaculateObject *(^)(NSInteger number))add {
__weak CaculateObject *weakSelf = self;
/* 返回一个block */
return ^CaculateObject* (NSInteger number){
weakSelf.result += number;
/* 这个block的返回值类型是调用者本身 */
return self;
};
}
@end
实际调用为:
CaculateObject *caculate = [[CaculateObject alloc] init];
caculate.add(33).add(23);
NSInteger sum = caculate.result;
/*结果 sum = 56 */
本篇主要说明了block的定义与用法,后面继续讨论block捕获自动变量(局部变量)的能力,未完待续……
参考链接
又见block(一):block是什么?
又见block(三):block实质
又见block(四):block捕获自动变量
又见block(五): __block变量和对象
又见block(六):block存储域与__block变量存储域
又见block(七):截获对象