您的位置:首页 > 其它

block简单用法 与传统回调 ---写的不错文章

2013-08-01 17:36 253 查看


Block的用法总结——写回调.

block是个什么玩意儿

Block是Apple Inc.为C、C++以及Objective-C添加的特性,使得这些语言可以用类lambda表达式的语法来创建闭包 ——维基百科
A block is an anonymous inline collection of code, and sometimes also called a "closure". ——Apple文档
闭包就是能够读取其它函数内部变量的函数。

这里简单总结一下用法。block的用法有很多种,最常用的有 回调 和 遍历 。这篇主要说 回调

回调
什么是回调

在计算机程序设计中,回调函数,或简称回调(Callback),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。 ——维基百科

回调就是说,我一个操作执行完成之后,提供给调用者一个接口,供调用者定义一些操作。obj-C的代理模式就是典型的回调。
举个简单的block例子:
@interface People : NSObject

-(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok;

@end

@implementaiton People

-(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok
{
NSLog(@"I have run out of my money");
aBlock();     //(1)
}

@end

这个时候, 就定义了一个带block参数的方法。这是一个很简单的block参数, 没有返回值, 没有参数。
当我们调用这个方法的时候,只需这样操作:
Peopeo *aPeople = [[People alloc] init]];
[aPeople runningOutOfMoneyUsingBlock:^{

NSLog(@"Earn more money!");

}];

这时在执行People类方法的时候,执行结果如下:
“I have run out of my mondy”
"Earn more money!"

很好理解,People的类方法有一个block参数。调用者在调用该方法的时候为block参数定义了若干操作(这里是输出一句话),然后将这些操作作为参数传递给类方法内部执行.调用者所定义的这些操作执行的位置,取决于"(1)"所处的位置。
如果将类方法的实现改变为:
-(void)runningOutOfMoneyUsingBlock:(void (^)(void))aBlok
{
aBlock();     //(1)
NSLog(@"I have run out of my money");
}

@end

那么运行结果就会变为:
"Earn more money!"
“I have run out of my money”

下面来说一说block 带参数 的情况,有People类方法定义如下:
@interface People : NSObject

-(void)runningOutOfMoneyUsingBlock:(void (^)(int a, int b))aBlok;

@end

@implementaiton People

-(void)runningOutOfMoneyUsingBlock:(void (^)(int a, int b))aBlok
{
NSLog(@"I have run out of my money");
int a = 10;
int b = 50
aBlock(a,b);     //(2)
}

@end

在这个类方法中,对之前的People类方法的block参数进行了扩展,加入了两个整形参数:a和b。在调用block之前为a和b赋值并且传给了block,形如(2)。
这个时候,当我们在调用这个类方法的时候,就会出现这样的情况:
Peopeo *aPeople = [[People alloc] init]];
[aPeople runningOutOfMoneyUsingBlock:^(int a, int b){

NSLog(@"a = %d, b = %d", a, b);

}];

执行结果如下:
"Earn more money!"
"a = 10, b = 50"

不难看出,People将自己内部的两个局部变量, 通过block传递给了调用者。这一点很好理解,想想我们经常使用的 代理方法 就可以了。
以UITableView的代理方法为例,代理方法定义如下
- (void)tableView(UITableView *):tableView didSelectRowAtIndexPath:(NSIndexPath)indexPath;

这个方法用来给某个section指定行数。私以为这个方法可以换为如下block实现。
@interface UITableView (WithBlock)

-(void)didSelectRowAtIndexPathUsingBlock:(void (^)(UItableView *tableView, NSIndxPath *indexPath))selectBlock;

@end

@implementation UITableView (WithBlock)

-(void)didSelectRowAtIndexPathUsingBlock:(void (^)(UItableView *tableView, NSIndxPath *indexPath))selectBlock
{
//some other code
...
if(selectBlock) {
selectBlock(self, indexPath);
}

…
//some other code
}

@end

好吧, 我承认这里给出这样的方法有点儿蹩脚,仅仅是为了对比Block和代理的相似之处。回想一下代理的实现,block是一样的原理。
block还可以有返回值,将block在调用者处执行的结果返回给方法本身。例如,再对以上实例方法进行扩展,代码如下:
@interface People : NSObject

-(void)runningOutOfMoneyUsingBlock:(int (^)(int a, int b))aBlok;

@end

@implementaiton People

-(void)runningOutOfMoneyUsingBlock:(int (^)(int a, int b))aBlock
{
NSLog(@"I have run out of my money");
int a = 10;
int b = 50
int m = 0;
if(aBlock)
{
m = aBlock(a,b);     //(2)
}
NSLog(@"aBlock的返回值为:%d",m);

}

@end

调用该方法:
[aPeople runningOutOfMoneyUsingBlock^(int a, int b){
return a + b;
}];

执行结果为:
"I have run out of money"
"aBlock的返回值为:60"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: