最近了解了下OC的链式语法,跟我们平时[obj xxx]
这种方法调用格式大相径庭。于是乎,自己也尝试着实现了如下调用方式:
UIView *view = [UIView new];
view.x.y.equalTo(5).with.w.h.equalTo(50);
NSLog(@"%@", NSStringFromCGRect(view.frame));
输出:{{5, 5}, {50, 50}}
完整Demo在这里:https://github.com/xiaoxm/ObjCChainingTest
这里简单记录下每种写法的实现机制:
view.x
回忆下,通常我们可以这样写一般是因为有一个property,而property会自动获得getter、setter方法。看代码:
//声明property x
@property (nonatomic, assign) CGFloat x;
//于是自动获得如下方法,�且不需要自己手动再写一遍
- (void)setX:(CGFloat)x;
- (CGFloat)x;
而view.x
会解析为调用方法- (CGFloat)x;
。同理,如果想要支持view.x
这种调用方式,只需要添加方法- (CGFloat)x;
即可。
view.x.y
将- (CGFloat)x;
�修改为- (UIView *)x;
。这样,view.x
执行后返回值仍旧为view对象,点语法继续调用,等同于view.x
、view.y
这两步。
view.equalTo(5)
首先我们来看下block的基本使用:
//例1
void (^block)() = ^(){
NSLog(@"无参数,无返回值");
};
block();
//例2
void (^block)(int) = ^(int val){
NSLog(@"仅参数:%d", val);
};
block(5);
//例3
int (^block)() = ^(){
return 5;
};
NSLog(@"仅返回值:%d", block());
//例4
int (^block)(int) = ^(int val){
return val + 1;
};
NSLog(@"有参数,有返回值:%d", block(5));
我们观察block的调用方式:block();
是不是有些启发了呢?
view.equalTo()
可以这么理解:view.equalTo
获取到一个block
,然后末尾加上()
便是调用这个block了。
于是乎,定义一个返回值为block的方法- (void (^)())equalTo;
便可以这样调用view.equalTo();
这里还需要一个输入参数,简单,修改block就好:- (void (^)(CGFloat))equalTo;
。于是最终调用便有了:view.equalTo(5)
以上,祝大家玩得开心~