Masonry 解析
在了解一个开源库之前,我们需要先搞清楚一件事情:
这个开源库解决了什么问题?
Masonry 解决了什么问题?
熟悉的人都知道:
Masonry 将 NSLayoutConstraint 进行了封装,使用了优雅高效易读的链式语法,让 Objective-C 开发者在手写 Autolayout 的时候不再那么麻烦。
因此,在看本文之前,你需要知道,什么是 Autolayout?
如果你已经知道什么是 Autolayout 了,那你至少还应该知道,如何使用代码来对视图添加约束?
现在应该知道,使用代码来写 Autolayout,苹果官方的 API 使用繁琐,代码量大,不易阅读。Masonry 非常完美的解决了这个问题。
Masonry 的 Github 地址:https://github.com/Masonry/Masonry
如果英语能力还可以的话,看它的 Github 里的 Readme 就能看明白很多东西。
这里有一个如何使用 Masonry 的教程写的不错:http://adad184.com/2014/09/28/use-masonry-to-quick-solve-autolayout/
Masonry 如何解决这些问题的?
我们先看看 NSLayoutConstraint 的创建方法:
// UIKit
// NSLayoutConstraint.h
/* Create constraints explicitly. Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant"
If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.
*/
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
看注释里面的,这段代码最终的结果是:
view1.attr1 = view2.attr2 * multiplier + constant
再来看它的使用:
// NSLayoutConstraint
[superView addConstraint:[NSLayoutConstraint constraintWithItem:view1
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:superView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:10]];
// 根据上面的定义,这段代码的结果是:
// view1.top = superView.top * 1.0 + 10;
// 再看看 Masonry 的做法
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(superview.mas_top).with.offset(10);
}];
// 简直完美!
Masonry 非常完美的解决了系统提供的复杂使用方式,让写出来的代码简洁,又易懂。
可以思考一下,如果我们要做这样一个封装,该怎么做?
思路:
我们首先需要一个类,就像 NSLayoutConstraint 一样,可以管理所有的东西,然后用简洁的输入方式输入所需要的内容,然后再调用一个方法,把需要的参数传递给 NSLayoutConstraint,并且生成,然后添加到 UIView 上。
最好是可以做到这样:
// 这将是我们的最终目标,请牢记这个,后面我们所有的想法,都是为了这个目标而努力。
view1.top = superView.top * 1.0 + 10;
所以我们需要的属性有上面的例子中所需要的所有东西:view1 , top , = , superView , top , 1.0 , 10. 根据 NSLayoutConstraint 的创建方法:
View1 和 superView 是 UIView 类型,
top 是 NSLayoutAttribute,
= 是 NSLayoutRelation,
1.0 是乘积, CGFloat 类型,
10 是偏移量 CGFloat 类型,
然后我们可以调用一个方法来完成这个约束的安装。
可是问题来了:
这跟系统提供的方法有什么区别呢?
Masonry 是如何实现链式语法的?
Masonry 类结构
Masonry 主要的类结构有:
MASConstraint:继承自 NSObject,是我们上一部分设想的那个类,负责收集 NSLayoutConstraint 的创建方法需要的参数,并给对应的 View 添加 Constraint,不过这个类只是基础的抽象类,只负责收集信息并且提供一些基础方法和属性。
MASViewConstraint