谈一谈我个人对Masonry的理解

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看206 回复回复3 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 206|回复: 3
收起左侧

谈一谈我个人对Masonry的理解

[复制链接]
baddy 发表于 2016-9-15 18:30:31 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑
我们先来看看是如何开始使用Masonry的,一般我们使用这个布局框架的时候,都会调用以下代码。。。。。

[Objective-C] 纯文本查看 复制代码
 [self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];


我们来分析下这段代码,UIView类型的使用了mas_makeConstraints这个方法,这个是写在分类里面的,有一个block参数,我们看一下里面的实现代码:

[Objective-C] 纯文本查看 复制代码
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);    return [constraintMaker install];
}


首先设置translatesAutoresizingMaskIntoConstraints属性为NO。

第二行初始化了一个MASConstraintMaker类,那这个类里面做了什么操作呢,好吧,本着刨根问底的精神我们继续往下看:

[Objective-C] 纯文本查看 复制代码
- (id)initWithView:(MAS_VIEW *)view {
    self = [super init];    if (!self) return nil;
    
    self.view = view;
    self.constraints = NSMutableArray.new;    
    return self;
}


将当前的view赋给maker类,然后初始化constraints,这是一个约束数组。

我们仔细看 block(constraintMaker); 这一行代码。。。

神马意思呢?

首先这个block是(void(^)(MASConstraintMaker *))类型的一个参数,我们其实可以更改为其它名称,感觉用block就有点混淆。。。

[Objective-C] 纯文本查看 复制代码
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))constraintMakerblock {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    constraintMakerblock(constraintMaker);    return [constraintMaker install];
}


比如可以更改为上面的形式...

这段代码的理解就是初始化了一个constraintMaker类,然后设置它的constraint属性,最后加载安装(install)。

[Objective-C] 纯文本查看 复制代码
 [self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];


注意:这种写法很容易理解为这是一个block,但其实只是在执行一个函数,后面一大块只不过是函数的一个参数而已,只不过它的参数是一个函数。

它等价与下面的一种写法:

[Objective-C] 纯文本查看 复制代码
self.view1.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self.view1];
constraintMaker.left.mas_equalTo(50);
constraintMaker.right.mas_equalTo(-50);
constraintMaker.top.mas_equalTo(50);
constraintMaker.bottom.mas_equalTo(-50);
[constraintMaker install];


那这样写的话就不是很方便了,那么有什么办法吗???

我们把它封装成一个函数???好的,封装成一个函数我们要做几件事情

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints
{    
   //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];    
    
    //设置它的属性  
    //  .........    
    
    //加载   
     [constraintMaker install];
}


那么第二步该怎么做呢?

传参数???但是参数有很多呀??怎么办??

比如我设置一个字典,里面用key,value来表示(left:50,right:-50,top:50,bottom:-50)好像也可以,但总觉的不是很方便

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints:(NSMutableDictionary *)dictionary
{   
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; 
       
    //设置它的属性 
     //  .........    
    constraintMaker.left.mas_equalTo([dictionary[@"left"] intValue]);
    constraintMaker.right.mas_equalTo([dictionary[@"right"] intValue]);
    constraintMaker.top.mas_equalTo([dictionary[@"top"] intValue]);
    constraintMaker.bottom.mas_equalTo([dictionary[@"bottom"] intValue]);    
    
    //加载    
    [constraintMaker install];
}
NSMutableDictionary *constraint=[[NSMutableDictionary alloc]init];
[constraint setObject:@"50" forKey:@"left"];
[constraint setObject:@"-50" forKey:@"right"];
[constraint setObject:@"50" forKey:@"top"];
[constraint setObject:@"-50" forKey:@"bottom"]; 
[self.view1 addMakeConstraints:constraint];


貌似也可以实现的额,那有没有什么更好地办法呢?我们看下第一种写法:

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints
{   
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];    
    
    //设置它的属性  
    //  .........    
    
    //加载    
    [constraintMaker install];
}


其实我们中间就是缺了一段代码:那可以使用delegate吗?

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints
{    
   //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    [self.del addConstraint:constraintMaker];    
    
    //加载    
    [constraintMaker install];
}

-(void)addConstraint:(MASConstraintMaker *)maker
{
    maker.left.mas_equalTo(50);
    maker.right.mas_equalTo(-50);
    maker.top.mas_equalTo(50);
    maker.bottom.mas_equalTo(-50);
}


既然可以用代理实现,那么block肯定也是可以的。

好的,我们改装成block版本:

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints
{    
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    self.makerBlock(constraintMaker);   
    
    //加载  
   [constraintMaker install];
}
[self.view1 addMakeConstraints];
self.view1.makerBlock=^(MASConstraintMaker *maker){
      
        maker.left.mas_equalTo(50);
        maker.right.mas_equalTo(-50);
        maker.top.mas_equalTo(50);
        maker.bottom.mas_equalTo(-50);
        
};


在这里,我们是作为一个属性来使用block的,那么我们还可以直接用参数作为block来实现的。

也就是说把这段代码封装成一个block参数:

[Objective-C] 纯文本查看 复制代码
-(void)addMakeConstraints:(void(^)(MASConstraintMaker *maker))maker
{    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    maker(constraintMaker);   
    //加载    [constraintMaker install];
}
 [self.view1 addMakeConstraints:^(MASConstraintMaker *make)
    {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];


至此,这段代码已经分析完毕,哈哈,总结就一句话:初始化MASConstraintMaker类,然后设置属性,最后加载,不同的就是将设置属性作为代码块调到实现的类里面来了而已。

好的 我们看下View+MASAdditions类:

[Objective-C] 纯文本查看 复制代码
/**
 *    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 TARGET_OS_IPHONE || TARGET_OS_TV@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;


这一段是对MASViewAttribute的声明,看它的名字就知道这一段是对NSLayoutAttribute的封装,我们知道NSLayoutAttribute只是一些属性的枚举,那么封装有什么意义呢?

好吧,我们看下这段代码:

[Objective-C] 纯文本查看 复制代码
 [self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.view1.mas_bottom).offset(10);
}];


有个self.view1.mas_bottom,我们知道要设置这个属性的话,要使用原生的方法:

[Objective-C] 纯文本查看 复制代码
NSLayoutConstraint *constaint=[NSLayoutConstraint constraintWithItem:self
                                                                       attribute:att
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:attribute.view
                                                                       attribute:attribute.attribute
                                                                      multiplier:1.0
                                                                        constant:space];


在这里有个toItem,那要设置toItem就必须知道当前是哪个view,如果只有NSLayoutAttribute属性的话,这段代码中得toItem是设置不了的。

所以MASViewAttribute便添加了view这个属性,方便这个地方的设置MAS---View---Attribute,可以这么理解,哈哈!

[Objective-C] 纯文本查看 复制代码
/**
 *  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(^)(MASConstraintMaker *make))constraintMakerblock;/**
 *  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(^)(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(^)(MASConstraintMaker *make))block;


这几个方法分别是添加约束,更新约束以及注销约束,前面已经将mas_makeConstraints这个方法讲的很详细了,后面两个方法类似。

只不过多了两个变量来控制:constraintMaker.updateExisting = YES;constraintMaker.removeExisting = YES;

好的,我们接着向下看:

[Objective-C] 纯文本查看 复制代码
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))constraintMakerblock {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    constraintMakerblock(constraintMaker);    return [constraintMaker install];
}


第一步:将maker的view设置为当前view

第二步:设置属性

第三步:加载

我们看下第二步:

[Objective-C] 纯文本查看 复制代码
make.left.mas_equalTo(50);
make.right.mas_equalTo(-50);
make.top.mas_equalTo(50);
make.bottom.mas_equalTo(-50);


第二步用的链式结构,如果不懂得话可以看看我之前的文章。

make.left返回的MASConstraint类型

[Objective-C] 纯文本查看 复制代码
- (MASConstraint * (^)(id attr))mas_equalTo;
- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo;
- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo;
- (MASConstraint * (^)(id))mas_equalTo {   
           return ^id(id attribute) {       
                 return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}


然后执行mas_equalTo的方法:

它的返回值是:MASConstraint * (^)(id) 一个block。

谈一谈我个人对Masonry的理解

谈一谈我个人对Masonry的理解 - 敏捷大拇指 - 谈一谈我个人对Masonry的理解

都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 贡献 +10 专家分 +10 收起 理由
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

cocoaswift 发表于 2016-9-18 09:21:22 | 显示全部楼层
不错~ mark~
蚊香酱 发表于 2016-9-24 15:34:46 | 显示全部楼层
不错的文章
JoyceChu 发表于 2016-9-28 02:34:52 | 显示全部楼层
好资料啊
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表