Masonry是一个用于布局的轻量级开源框架,我们一般使用它来代替苹果原生的AutoLayout代码,使得代码更加舒适简洁。Masonry框架虽然很轻量,但是代码中使用了大量的block和链式编程的技巧,所以想要阅读Masonry框架源码,需要掌握这两方面的知识
Block的常见使用
- 声明block类型变量
int (^test)(int) = ^(int a) {
return a + 1;
};
- block作为函数参数
- (void)test :(void (^)(NSString *a)) block {
}
- block作为函数返回值
- (void (^)(NSString *))block {
return ^(NSString *a) {
NSLog(@"%@",a);
};
}
有时候我们也可以使用typedef来简化block
typedef void(^block)(NSString *a);
- (block)block {
return ^(NSString *a) {
NSLog(@"%@",a);
};
}
- (void)test :(block) block {
}
链式编程思想
很多地方总会将链式编程和函数式编程结合在一起来谈论,这里先简单说明下两者的区别
-
函数式编程:
将函数作为和其他数据类型一样来进行操作,可以作为其他函数的参数和返回值等,例如:
method1(method2(method3(3)));
-
链式编程
用点的形式连接函数,完成参数的传递和逻辑处理,例如:
make.top.equalTo(self.view).with.offset(5);
接着我们来看链式编程是如何实现的
还是用一个最经典的例子来看,那就是计算器,我们先来看看整体的代码,再逐步分析
- .h文件
@property (nonatomic, assign) NSInteger result;
+ (NSInteger)makeCalculator :(void(^)(Calculator * make)) block;
- (Calculator * (^) (NSInteger))add;
- (Calculator * (^) (NSInteger))sub;
- (Calculator *)printResult;
- .m文件
+ (NSInteger)makeCalculator:(void (^)(Calculator * make))block {
Calculator *calculator = [[Calculator alloc]init];
block(calculator);
return calculator.result;
}
- (Calculator *(^)(NSInteger))add {
return ^(NSInteger temp) {
self.result += temp;
return self;
};
}
- (Calculator *(^)(NSInteger))sub {
return ^(NSInteger temp) {
self.result -= temp;
return self;
};
}
- (Calculator *)printResult {
NSLog(@"%ld",(long)self.result);
return self;
}
- 使用
[Calculator makeCalculator:^(Calculator *make) {
make.add(2).sub(1).printResult.sub(3);
}];
看.h文件,有一个result成员属性来存储结果,方法大致分为了三种
-
类方法:makeCalculator
- 使用了block做参数,block中有一个Calculator对象
- 在实现中:
- 初始化Calculator对象
- 交付给block作为参数
- 返回值为成员变量result
-
返回block的方法:add、sub
- 使用了block作为返回值
- 实现中:
- 操作成员变量result
- 返回自身(链式编程的核心)
-
返回对象的方法:printResult
- 返回自身对象(满足链式编程)
- 打印操作
在看使用的代码
- 类方法的调用
-
链中的方法:
make.add(2).sub(1).printResult.sub(3);
可以发现在链中的调用都是通过点进行的,但是在OC中都是通过
[object method] 的形式调用的,这里分为两种:-
返回值为block的方法:
- 首先该方法返回值是一个block,调用起来相当于getter方法,所以等价于一个block的属性
@property (nonatomic, readonly) Calculator * (^add) (NSInteger);
- 调用过程可以分为两步:
- 第一步:
(Calculator * (^)(NSInteger)) tempBlock = make.add;
这里make.add是获取了属性 - 第二步:
tempBlock(2);
- 首先该方法返回值是一个block,调用起来相当于getter方法,所以等价于一个block的属性
-
返回值为对象的方法:
- 在OC中,如果符合getter方法的格式,则可以通过点语法进行调用
-
返回值为block的方法: