博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
masonry更新xib约束探索
阅读量:6832 次
发布时间:2019-06-26

本文共 4096 字,大约阅读时间需要 13 分钟。

一个有趣的实验

首先做个简单的小实验,在storyboard拖放一个view,添加好约束。之后利用masonry分别去更新这个视图的位置,尺寸。会发现不一样的结果。

//更新尺寸- (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event{ [super touchesBegan:touches withEvent:event]; [self.viewTest mas_updateConstraints:^(MASConstraintMaker *make) { //和storyboard中的约束相同 make.width.mas_equalTo(375.0); }];}//更新位置- (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event{ [super touchesBegan:touches withEvent:event]; [self.viewTest mas_updateConstraints:^(MASConstraintMaker *make) { //和storyboard中的约束相同 make.left.equalTo(self.viewTest.superview); }];}复制代码

如果你这么做会惊奇的发现更新位置有效,更新尺寸无效。why?到底用masonry能不能更新xib上的约束?带着这个问题我们去深入探索。

探索

第一步:查看源代码

其实上面两个小实验控制台都有打印警告

大致意思是说约束冲突。分析控制台中的两个约束,第二个应该是xib上的约束(有个55常量),第一个是我们更新后多出来的(MASLayout)。

那说明mas_updateConstraints导致多出来一个约束导致了约束冲突。让我们看看源代码。

//调用代码- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {    self.translatesAutoresizingMaskIntoConstraints = NO;    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];    //更新存在的约束    constraintMaker.updateExisting = YES;    block(constraintMaker);    return [constraintMaker install];}//最终要执行的代码- (void)install {    if (self.hasBeenInstalled) {        return;    }    .......     MASLayoutConstraint *existingConstraint = nil;    //判断是否更新存在约束(刚刚这里赋值了YES)    if (self.updateExisting) {        //下边去当前view上的约束里去匹配传过来的约束,如果相同返回这个约束,否则nil        existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];    }    //找到了匹配的约束    if (existingConstraint) {        // just update the constant        //更新约束的值        existingConstraint.constant = layoutConstraint.constant;        self.layoutConstraint = existingConstraint;    } else {        //没找到匹配约束就在当前view上添加外边传过来的约束        [self.installedView addConstraint:layoutConstraint];        self.layoutConstraint = layoutConstraint;        [firstLayoutItem.mas_installedConstraints addObject:self];    }}//遍历匹配当前view上的约束- (MASLayoutConstraint *)layoutConstraintSimilarTo:(MASLayoutConstraint *)layoutConstraint {    // check if any constraints are the same apart from the only mutable property constant    // go through constraints in reverse as we do not want to match auto-resizing or interface builder constraints    // and they are likely to be added first.    /** 大致意思是倒序遍历查找约束,过滤掉了auto-resizing,interface builder 上的约束,也就是说遍历时候不考虑xib上的约束这样碰到xib上的约束后就直接continue了,最终会找不到匹配的约束返回nil */    for (NSLayoutConstraint *existingConstraint in self.installedView.constraints.reverseObjectEnumerator) {        if (![existingConstraint isKindOfClass:MASLayoutConstraint.class]) continue;        if (existingConstraint.firstItem != layoutConstraint.firstItem) continue;        if (existingConstraint.secondItem != layoutConstraint.secondItem) continue;        if (existingConstraint.firstAttribute != layoutConstraint.firstAttribute) continue;        if (existingConstraint.secondAttribute != layoutConstraint.secondAttribute) continue;        if (existingConstraint.relation != layoutConstraint.relation) continue;        if (existingConstraint.multiplier != layoutConstraint.multiplier) continue;        if (existingConstraint.priority != layoutConstraint.priority) continue;        return (id)existingConstraint;    }    return nil;}复制代码

通过上面分析我们知道了,xib上的约束是不去匹配的最终existingConstraint被赋值了nil。导致最终执行了[self.installedView addConstraint:layoutConstraint];新加了一个约束。而这个新的约束往往是最高优先级的,并且xib上的约束发现默认也是最高优先级所以导致了约束冲突。控制台打印了警报。

第二步:验证

步骤一分析得出的结论是mas_updateConstraints方法导致新增了一个同优先级的约束导致了约束冲突。那我们尝试去改一下xib上的相应约束的优先级,调低些。在运行代码发现控制台并没有报错输出,同时无论更新尺寸还是位置都有效。这也进一步验证了步骤一的结论。

总结

通过以上分析得出,masonry不能直接更新xib上的约束。如果我们用mas_updateConstraints方法,masonry会新增一个约束,有可能会导致约束冲突,控制台打印警报,视图布局错乱。

那怎么去更新xib上的约束的。有两个方案,一是脱出来约束直接修改值。二是改变xib上的对应约束优先级,把优先级调低。然后用masonry去添加更高优先级的约束即可。相比较而言觉得方式一更好些。因为更改优先级其实就是要废掉xib上的约束,不够直接麻烦。

疑问

一开始的两个小实验,因为masonry不能直接更新xib上的约束,导致mas_updateConstraints方法实际上是新增了一个最高优先级的约束,导致约束冲突,控制台打印警报。这可以解释通。

但是为什么同样都是约束冲突,尺寸的约束冲突视图界面会用xib的约束。位置的约束冲突视图界面则用masonry的约束让人费解。还有待探索。

转载于:https://juejin.im/post/5cf1d92df265da1b725be9d1

你可能感兴趣的文章
使用python写糗事百科的爬虫
查看>>
$MFTMirr does not match $MFT (record 0)问题解决
查看>>
oracle 修改列
查看>>
python-03:用最简单快速的方法入门
查看>>
CentOS7网卡绑定
查看>>
LAMP-HTTPD服务器配置
查看>>
linux安装ICMP shell(icmp后门)
查看>>
JSP 上传图片之前先在页面生成预览
查看>>
ICMP协议-路由交换原理4-【HCNA笔记】
查看>>
Performing RMAN Tablespace Point-in-time Recovery(TSPITR)
查看>>
弱引用研究
查看>>
JQuery 判断checkbox是否选中,checkbox全选,获取checkbox选中值
查看>>
高考焦虑现象源于就业焦虑
查看>>
Lync Server 2013企业版部署系列之二:准备DNS
查看>>
启动3个线程轮番打印递增的数字
查看>>
PHP FLUSH 函数 在IE11中 清除缓存的方法
查看>>
lvm相关知识
查看>>
[转] 《全唐诗》《全宋词》
查看>>
C Primer Plus (第五版) 第二章 编程练习
查看>>
安卓开发中Theme.AppCompat.Light的解决方法
查看>>