看這篇博客時 "最快讓你上手ReactiveCocoa之基礎篇" 看到作者介紹鏈式編程那一塊,發現自己的鑽研精神不足。想想自己使用鏈式編程也有段時間了,對,就是 Masonry 庫。自己一直享受點語法帶來的效率提升,卻沒想過自己去照著實現一下,真是慚愧。 好吧,本著發現問題就要立即解決問題的一貫原則 ...
看這篇博客時最快讓你上手ReactiveCocoa之基礎篇看到作者介紹鏈式編程那一塊,發現自己的鑽研精神不足。想想自己使用鏈式編程也有段時間了,對,就是 Masonry 庫。自己一直享受點語法帶來的效率提升,卻沒想過自己去照著實現一下,真是慚愧。
好吧,本著發現問題就要立即解決問題的一貫原則,就看一看鏈式語法的實現方法。
現在做一個加減乘除計算。
在 Masonry 里,我們常用的添加約束的方法就是 mas_makeConstraints:
// View+MASAdditions
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);
return [constraintMaker install];
}
在約束里,用到 left, right 等是 constraintMaker 的屬性,最後設置參數,比如 offset() 是 MASConstraint 的方法:
//MASConstraintMaker
@property (nonatomic, strong, readonly) MASConstraint *left;
- (MASConstraint *)left {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
}
//MASConstraint
- (MASConstraint * (^)(CGFloat offset))offset;
- (MASConstraint * (^)(CGFloat))offset {
return ^id(CGFloat offset){
self.offset = offset;
return self;
};
}
所以源碼大概的結構是這樣。然後就要實現我們的計算器了。
//NSObject+Extension
@implementation NSObject (Calculator)
- (CGFloat)makeCalculators:(void (^)(CalculatorMaker *))block {
CalculatorMaker *mgr = [[CalculatorMaker alloc] init];
block(mgr);
return mgr.result;
}
@end
//CalculatorMaker.h
@interface CalculatorMaker : NSObject
@property (nonatomic, assign) int result;
- (CalculatorMaker *(^)(int)) add;
- (CalculatorMaker *(^)(int)) sub;
- (CalculatorMaker *(^)(int)) mul;
- (CalculatorMaker *(^)(int)) div;
@end
//CalculatorMaker.m
@implementation CalculatorMaker
- (CalculatorMaker *(^)(int))add {
return ^CalculatorMaker *(int value) {
_result += value;
return self;
};
}
- (CalculatorMaker *(^)(int))sub {
return ^CalculatorMaker *(int value) {
_result -= value;
return self;
};
}
- (CalculatorMaker *(^)(int))mul {
return ^CalculatorMaker *(int value) {
_result *= value;
return self;
};
}
- (CalculatorMaker *(^)(int))div {
return ^CalculatorMaker *(int value) {
_result /= value;
return self;
};
}
@end
//main.m
int result = [NSObject makeCalculators:^(CalculatorMaker *make) {
make.add(1).add(5).mul(2);
}];
//output 12
看 add() 方法,返回類型是自身所在 CalculatorMaker 類型的 Block,而 Block 返回的也是 self
,所以可以連續使用鏈式調用。不過關於為什麼可以用點語法,這個我有點暈,按說 make.add 是 OC 語法,後面括弧跑到 Block 里去。那對於 OC 語法來說,點語法是針對 getter 方法的,對於沒有參數的非 getter 方法也可以調用,但調用時會報 warning ,所以這點不是很懂。
關於鏈式調用的寫法,有點秀技術的感覺。視情況而用。不過,鑒於 Masonry 作者能寫出這麼有技巧的代碼,我覺得有必要研究一下 Masonry 源碼了。