编程思想在iOS
的应用中大概有那么几类,咱们最经常使用的当属于面向对象的编程思想,一切皆对象,基于这种思想离不开的就是咱们最经常使用的封装、继承、多态。平时工做中咱们也会接触一些面向协议的编程思想,好比说接口分离解耦合,再好比说咱们最经常使用的delegate
都是面向协议的思想,还有就是基于ReactiveCocoa
框架也就是平时听到的RAC提供的响应式编程思想,今天主要分析下另外一种编程思想,链式编程。编程
Masonry
框架做为iOS
开发者耳熟能详,你们在作纯代码适配的时候应该都曾用过,下面就以Masonry
为例,但本文不过多的分析MAS
源码,旨在提炼思想。数组
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);
return [constraintMaker install];
}
- (id)initWithView:(MAS_VIEW *)view {
self = [super init];
if (!self) return nil;
self.view = view;
self.constraints = NSMutableArray.new;
return self;
}
复制代码
1.建立约束制造者MASConstraintMaker
而且绑定控件,在约束制造者init
的同时生成了一个保存全部约束的数组constraints
。bash
2.执行mas_makeConstraints
传入的block
,返回咱们刚才建立的约束制造者constraintMaker
。框架
3.让约束制造者安装约束,执行install
方法。函数
- (NSArray *)install {
if (self.removeExisting) {
NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
for (MASConstraint *constraint in installedConstraints) {
[constraint uninstall];
}
}
NSArray *constraints = self.constraints.copy;
for (MASConstraint *constraint in constraints) {
constraint.updateExisting = self.updateExisting;
[constraint install];
}
[self.constraints removeAllObjects];
return constraints;
}
复制代码
其实是遍历了咱们建立约束制造者
constraintMaker
时所建立的constraints
,constraints
里面实际上存储的是咱们为控件添加的全部约束信息,而后分别对每条约束之行install
。那么问题来了,constraints
里面的约束从哪里来的呢。这就要回到了上面说的第2
步,block
将约束制造者返回给用户,让用户经过constraintMaker
去设置控件的约束,这些约束实际上就是存储到了constraints
中。当执行第3
步return [constraintMaker install];
的时候,就是将全部调用者添加的布局转换为NSLayoutConstraint
对象也就是咱们熟悉的纯代码适配,进行布局更新。布局
实际上Masonry
就是基于链式编程思想实现的开源框架,即强大,又直观。好比说咱们在使用Masonry
的时候一般会这样写:ui
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.top.mas_equalTo(44);
make.left.mas_equalTo(5);
make.centerY.equalTo(self);
}];
复制代码
为何make
能够一直这么点下去,点语法给咱们的第一感受是get
方法,实际上确实是get
方法:spa
- (MASConstraint *)height {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
}
复制代码
经过源码能够看到.height
实际上返回的并非一个int
或者NSInteger
类型变量,而是MASConstraint
,是约束制造者自己,实际上每次调用.height就是将约束添加到咱们上面提到的constraints数组中。到这里,链式编程的特色就显而易见了,那就是方法返回值必需要有方法的调用者
。那么还有疑问,mas_equalTo()
是什么鬼。下面着重讲一下.mas_equalTo()
,code
仍是经过源代码点进去看一下:对象
- (MASConstraint * (^)(id))equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
复制代码
返回值是一个MASConstraint * (^)(id)
的block
类型,到这里咱们了解了.mas_equalTo
其实是返回了一个返回值为MASConstraint
类型的block
,当咱们外面调用block
的时候实际上执行的是self.equalToWithRelation(attribute,NSLayoutRelationEqual);
函数,没错,它返回的依旧是MASConstraint
类型,依旧是方法的调用者,也就是前面提到的约束制造者,因此咱们在调用mas_equalTo()
以后还能继续点下去,像不像个无底洞。若是这样很差理解的话咱们能够将添加约束的源码改写一下来实现:
[view mas_makeConstraints:^(MASConstraintMaker *make) {
// make.height.top.mas_equalTo(44);
MASConstraint * (^)(id)block = make.height.top.mas_equlTo;
MASConstraint *make = block(44);
make.top...
}];
复制代码
这下应该就很好理解了。
最后总结一下什么是链式编程,一句话就是方法返回值必需要有方法的调用者!