版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.07.16 |
前言
我们做APP界面,也就是布局UI,那么关于布局,我们有很多方法,苹果也都提供了支持,市场上我们用的并不是系统提供原生的layout,对于OC语言一般都是使用一个第三方的布局框架 —— Masonry。接下来几篇我们就一起深入看一下这个框架。感兴趣的看上面几篇文章。
1. Masonry框架详细解析(一) —— 基本概览(一)
基本结构和API
首先我们看一下框架的基本结构。
接着,一起看一下API接口
Masonry.h
#import
//! Project version number for Masonry.
FOUNDATION_EXPORT double MasonryVersionNumber;
//! Project version string for Masonry.
FOUNDATION_EXPORT const unsigned char MasonryVersionString[];
#import "MASUtilities.h"
#import "View+MASAdditions.h"
#import "View+MASShorthandAdditions.h"
#import "ViewController+MASAdditions.h"
#import "NSArray+MASAdditions.h"
#import "NSArray+MASShorthandAdditions.h"
#import "MASConstraint.h"
#import "MASCompositeConstraint.h"
#import "MASViewAttribute.h"
#import "MASViewConstraint.h"
#import "MASConstraintMaker.h"
#import "MASLayoutConstraint.h"
#import "NSLayoutConstraint+MASDebugAdditions.h"
一起看一下这个API框架结构。
约束入口
我们都是对视图进行约束,所以入口就是一个UIView的分类。
View+MASAdditions.h
大家对这个入口应该很熟悉吧
#import "MASUtilities.h"
#import "MASConstraintMaker.h"
#import "MASViewAttribute.h"
/**
* Provides constraint maker block
* and convience methods for creating MASViewAttribute which are view + NSLayoutAttribute pairs
*/
@interface MAS_VIEW (MASAdditions)
/**
* following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute
*/
@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline;
#endif
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;
#endif
#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0));
#endif
/**
* a key to associate with this view
*/
@property (nonatomic, strong) id mas_key;
/**
* Finds the closest common superview between this view and another view
*
* @param view other view
*
* @return returns nil if common superview could not be found
*/
- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view;
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created MASConstraints
*/
- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* If an existing constraint exists then it will be updated instead.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* All constraints previously installed for the view will be removed.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
@end
这里有几点需要说明:
1. 几个属性
首先我们看一下几个属性
/**
* following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute
*/
@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);
这里,这些属性返回一个当前view的一个新的MASViewAttribute
以及合适的NSLayoutAttribute
。
我们先看一下这个返回的MASViewAttribute
对象
/**
* An immutable tuple which stores the view and the related NSLayoutAttribute.
* Describes part of either the left or right hand side of a constraint equation
*/
@interface MASViewAttribute : NSObject
这个对象是一个存储视图和相关NSLayoutAttribute
的不可变元组。描述约束方程左侧或右侧的一部分。
2. 宏判断
接着就是几个宏判断。
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline;
#endif
#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;
#endif
#if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000) || (__TV_OS_VERSION_MAX_ALLOWED >= 110000)
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuide API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideTop API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideBottom API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideLeft API_AVAILABLE(ios(11.0),tvos(11.0));
@property (nonatomic, strong, readonly) MASViewAttribute *mas_safeAreaLayoutGuideRight API_AVAILABLE(ios(11.0),tvos(11.0));
#endif
可能有人会问,这块是做什么的,其实就是根据不同系统定义的不同属性,比如说11系统出来的safeAreaLayoutGuide
,这个就只有在11系统中使用,所以才需要进行版本判断。
// 表示系统大于8.0
__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
// 当前SDK的最高版本, 在手机上, 就是该手机上支持的SDK最高版本,这里表示最大的支持的版本是11.0
__IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
3. 几个重要入口方法
下面这几个方法大家都用过,也是Masonry应用的基本入口,下面我们就分着看一下。
1)寻找两个视图的最近的父视图
/**
* Finds the closest common superview between this view and another view
*
* @param view other view
*
* @return returns nil if common superview could not be found
*/
- (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view;
该方法的作用就是寻找本视图和另外一个视图最近的父视图。这个我们用的其实比较少,大家熟悉理解下就好。
2)make构建约束
我们一般使用下面这个方法构建约束。
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created MASConstraints
*/
- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
这个方法大家基本都用过,也是最熟悉的,就是用来进行约束的。该方法根据传入的view创建一个MASConstraintMaker
,一旦block结束执行,任何定义的约束都被添加到view或者合适的superview
上。返回值就是一个创建的MASConstraints
数组。
3)update约束
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* If an existing constraint exists then it will be updated instead.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
该方法根据传入的view创建一个MASConstraintMaker
,一旦block结束执行,任何定义的约束都被添加到view或者合适的superview
上。如果一个约束存在,那么它会替代到本次更新的约束。返回值是一个创建的/更新的约束的数组。
4)remake约束
/**
* Creates a MASConstraintMaker with the callee view.
* Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
* All constraints previously installed for the view will be removed.
*
* @param block scope within which you can build up the constraints which you wish to apply to the view.
*
* @return Array of created/updated MASConstraints
*/
- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
该方法用于根据传入的view创建一个MASConstraintMaker
,一旦block结束执行,任何定义的约束都被添加到view或者合适的superview
上。该view的所有以前的约束都将被remove掉,返回值是一个创建的/更新的约束的数组。该方法与update的区别是,update是更新相同的约束,而remake是完全删除以前的约束,使用本次重新创建的约束。
你为什么可以make很多个布局属性
其实这个是一个响应式编程的问题,我们在使用的时候一般都是下面这种类似的使用方式。
make.height.width.equalTo(@(100));
这里的make其实是block的回调,带的类型的参数MASConstraintMaker
,MASConstraintMaker
从名字上大家都可以猜测的差不多,这个其实就是进行约束的工厂方法。
@property (nonatomic, strong, readonly) MASConstraint *width;
@property (nonatomic, strong, readonly) MASConstraint *height;
... ...
当我们调用make.height的时候其实就是实现了下面这个方法
- (MASConstraint *)height {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
}
该getter方法返回的是一个MASConstraint
对象,
然后调用.width
方法,就会调用MASConstraint
对象中width的getter方法。
/**
* Creates a new MASCompositeConstraint with the called attribute and reciever
*/
- (MASConstraint *)width;
getter
方法实现如下所示:
- (MASConstraint *)width {
return [self addConstraintWithLayoutAttribute:NSLayoutAttributeWidth];
}
大家可以看见返回的仍然是MASConstraint
,所以你就一直可以点语法进行约束。
关于这个以后会分篇幅进行详细的说明,这里只是简单的提一下。
参考文章
1. __IPHONE_OS_VERSION_MIN_REQUIRED 和 __IPHONE_OS_VERSION_MAX_ALLOWED
2. iOS开发之Masonry框架源码解析
后记
本篇主要讲述了基本结构API和约束入口,感兴趣的给个赞或者关注~~~~