内容简介:编程思想在实际上是遍历了我们创建约束制造者
编程思想在 iOS
的应用中大概有那么几类,我们最常用的当属于面向对象的编程思想,一切皆对象,基于这种思想离不开的就是我们最常用的封装、继承、多态。平时工作中我们也会接触一些面向协议的编程思想,比如说接口分离解耦合,再比如说我们最常用的 delegate
都是面向协议的思想,还有就是基于 ReactiveCocoa
框架也就是平时听到的RAC提供的响应式编程思想,今天主要分析下另一种编程思想,链式编程。
首先简单分析一下Masonry的实现过程:
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
。 -
2.执行
mas_makeConstraints
传入的block
,返回我们刚才创建的约束制造者constraintMaker
。 -
3.让约束制造者安装约束,执行
install
方法。
我们再看一下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
就是基于链式编程思想实现的开源框架,即强大,又直观。比如说我们在使用 Masonry
的时候通常会这样写:
[view mas_makeConstraints:^(MASConstraintMaker *make) { make.height.top.mas_equalTo(44); make.left.mas_equalTo(5); make.centerY.equalTo(self); }]; 复制代码
为什么 make
可以一直这么点下去,点语法给我们的第一感觉是 get
方法,实际上确实是 get
方法:
- (MASConstraint *)height { return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight]; } 复制代码
通过源码可以看到 .height
实际上返回的并不是一个 int
或者 NSInteger
类型变量,而是 MASConstraint
,是约束制造者本身,实际上每次调用.height就是将约束添加到我们上面提到的constraints数组中。到这里,链式编程的特点就显而易见了, 那就是方法返回值必须要有方法的调用者
。那么还有疑问, mas_equalTo()
是什么鬼。下面着重讲一下 .mas_equalTo()
,
还是通过源代码点进去看一下:
- (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... }]; 复制代码
这下应该就很好理解了。
最后总结一下什么是链式编程,一句话就是方法返回值必须要有方法的调用者!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 浅析阿里分布式事务组件 fescar 2pc 的设计思想
- 常用算法思想之动态规划的后缀思想
- 常用算法思想之动态规划的区间子集思想
- Linux 背后的思想
- 深入简出-- iOS编程思想
- 前端架构思想:聚类分层
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Making Things See
Greg Borenstein / Make / 2012-2-3 / USD 39.99
Welcome to the Vision Revolution. With Microsoft's Kinect leading the way, you can now use 3D computer vision technology to build digital 3D models of people and objects that you can manipulate with g......一起来看看 《Making Things See》 这本书的介绍吧!