(一一八)利用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

posted on 2015-08-11 22:26  张大大123  阅读(144)  评论(0编辑  收藏  举报

导航