在开始之前,先贴一张图片,表明为什么需要将Block,代理,通知和KVO放在一起。
由上图可知,Block,代理,通知和KVO都能实现数据传递的功能,可以根据不同的情景选择合适的方式
Block
声明
// 使用typedef为block变量定义别名
// 解释:将一个返回值为double,参数为int的block取一个Rename的别名
typedef double (^Rename)(int);
// Block作为属性的写法
@property (nonatomic,copy) int (^sumOfTwoNumber)(int,int);
// 使用typedef后的block声明变量
@property (nonatomic,copy) Rename divideByTwo;
赋值
// 直接为block赋值
self.sumOfTwoNumber = ^(int a,int b){
return a + b;
};
// 调用block
NSLog(@"%zd",self.sumOfTwoNumber(10,10));
参数
/**
* block作为方法参数的的写法
* @param before 只是为了说明如果不只有一个block参数,那该怎么写
* @param aBlock block参数
*
* @return block返回的整数值
*/
- (int) blockParam:(NSString *)before Block:(int (^)(int,int)) aBlock {
// 模拟数据的处理
if (arc4random_uniform((unsigned int)before.length) % 2 == 0) {
// 执行block
return aBlock(2,(int)before.length);
}
return aBlock(1,(int)before.length);
}
/// 不使用block实现相同功能
- (int) nonBlockParam:(NSString *)before {
// 模拟数据的处理
if (arc4random_uniform((unsigned int)before.length) % 2 == 0) {
return 2 + (int)before.length;
}
return 1 + (int)before.length;
}
返回值
NSLog(@"%f",self.divideByTwo(5));
// MARK: - 懒加载block
- (Rename)divideByTwo {
if (_divideByTwo == nil) {
_divideByTwo = ^(int param){
return param / 2.0;
};
}
return _divideByTwo;
}
价值(个人观点)
block是一段预先准备的代码块,它和函数非常的类似,
// 调用方法来传递block,并返回
int result = [self blockParam:@"Jus for test" Block:self.sumOfTwoNumber];
- (int) blockParam:(NSString *)before Block:(int (^)(int,int)) aBlock {
使用了代码块作为参数,真正执行的时是根据预先定义的
return a + b
来完成的
接收者是预先定义的sumOfTwoNumber
发送者是- (int) blockParam:(NSString *)before Block:(int (^)(int,int)) aBlock
,接收者做为参数传递而发送者又回调了接收者,所以实现了数据的双向传递
代码块的好处是什么呢? 如果只从上面的- (int) nonBlockParam:(NSString *)before
来进行对比,代码块似乎没有什么用,但是我们可以换个角度去思考,如果nonBlockParam:
是系统或第三方框架提供的方法,我们一般修改它的代码,现在要求在处理完之后,不是要a + b,而是a - b,那就稍微不太妙了,当然我们也可以将需要改变的代码抽取出来,然后写个方法,那也可以实现需求,但是两种方式的实现,block感觉更漂亮一些。