Objective C 鏈式呼叫

canopus4u發表於2015-09-11

起因

某日使用DKChainableAnimationKit的時候發現可以如下寫程式碼:

view.animation.rotate(180).anchorTopLeft.thenAfter(1.0).rotate(90).anchorCenter.animanimation

無獨有偶。Masonry其實也是這樣用的

make.right.equalTo(self.view).with.offset(-10);

原理

看了一下程式碼,其實就是通過一個實現了所有方法的Chaining Method Object,每一個方法都返回一個`Block
, 這個Block返回型別為Chaining Method ObjectBlock`的引數為你想要傳入的引數型別。

@interface ChainingMethodObject : NSObject
- (ChainingMethodObject * (^)(void))doA;
- (ChainingMethodObject * (^)(NSInteger i))doB;
- (ChainingMethodObject * (^)(NSString* str))doC;
- (ChainingMethodObject * (^)(NSString* str, NSArray* array))doD;
@end

@implementation ChainingMethodObject
- (ChainingMethodObject * (^)(NSInteger i))doB{
    return ^id(NSInteger i) {
        //do actual stuff related with B
        return self;
    };
}
...其他方法類似
@end

通常情況下,ChainingMethodObject都會有delegate存在,具體視實際運用情況而定,如動畫庫DKChainableAnimationKit中,animation裡有個weak var view:UIView指向UIView從而對target View進行操作。

@implementation ChainingMethodObject
- (id) initWithObject:(id)obj{
    self = [super init];
    _delegate = obj;
    return self;
}
@end
@interface HostObject()
ChainingMethodObject * _cObj;
@end
@implementation HostObject (ChainingMethodObject)
- (ChainingMethodObject *) getChainingMethodObject{
    if (!_cObj)
        _cObj = [[ChainingMethodObject alloc] initWithObject:self];
    return _cObj;
}
@end

然後就可以了:

HostObject* hostObject = [HostObject new];
[hostOjbect getChainingMethodObject].doA.doC(@"Hi there!").doD(@"Hello",@[@1,@2]).doB(100).doA;

參考

DKChainableAnimationKit

Masonry

原作寫於segmentfault 連結

相關文章