(一一八)利用block实现链式编程
有些时候需要不断地调用方法,如果使用传统方案,需要拿到对象多次调用,例如有一个Ball对象,实现了up、down、left、right四个方法,分别控制球的运动方向,如果要实现球向右再向下,需要这么写:
[ball right]; [ball down];如果能够按照下面这样写,会更加方便。
[[ball right] down];
要实现这样的功能十分简单,只要每个方法都返回self即可,但是如果调用次数多,会有很多个中括号。如果能改造成后面这样,会更好。
ball.right().down();要实现这么调用方法,可以用结构体,让方法返回一个结构体,这时候加上(),相当于执行一个结构体,例如有个结构体名称为block1,无参数,调用方法为block1(),因此我们写ball.right()相当于拿到了返回的block进行执行。需要注意的是,为了能够通过点语法执行方法,方法不能有参数,否则只能用中括号,参数要传递,通过block即可。
下面的代码实现了四个无参方法和一个有参方法:
#import <Foundation/Foundation.h> @interface Ball : NSObject - (Ball *(^)())up; - (Ball *(^)())down; - (Ball *(^)())right; - (Ball *(^)())left; - (Ball *(^)(NSString *sth))doSomething; @end
#import "Ball.h" @implementation Ball - (Ball *(^)())up{ return ^{ NSLog(@"up"); return self; }; } - (Ball *(^)())down{ return ^{ NSLog(@"down"); return self; }; } - (Ball *(^)())right{ return ^{ NSLog(@"left"); return self; }; } - (Ball *(^)())left{ return ^{ NSLog(@"right"); return self; }; } - (Ball *(^)(NSString *))doSomething{ return ^(NSString *sth){ NSLog(@"do <%@>",sth); return self; }; } @end注意结构体的写法即可,每个方法内部直接返回结构体,需要做的事情直接在结构体内完成。
测试这个类的链式调用:
#import <Foundation/Foundation.h> #import "Ball.h" int main(int argc, const char * argv[]) { @autoreleasepool { Ball *b = [[Ball alloc] init]; b.up().down().right().doSomething(@"rotate").left(); // 方法不能有参数,否则只能用中括号调用方法。 // 参数通过block接收 // b.up返回了block,()表示调用block,从这里可以传入参数 } return 0; }打印出的数据:
2015-08-11 22:16:23.777 链式编程[14240:145326] up 2015-08-11 22:16:23.778 链式编程[14240:145326] down 2015-08-11 22:16:23.778 链式编程[14240:145326] left 2015-08-11 22:16:23.779 链式编程[14240:145326] do <rotate> 2015-08-11 22:16:23.779 链式编程[14240:145326] right