先简单介绍一下,这几个方法的使用场景
mas_makeConstraints
: 一个视图,刚创建出来,没有任何约束。用这个方法,给视图创建 x,y,w,h的约束。
mas_updateConstraints
: 一个视图,之前已经有约束了,因为条件变了,需要变位置(x,y),变宽高(w,h),需要修改约束。
mas_remakeConstraints
: 一个视图,之前有约束,但之前的约束,全都不要了(x,y,w,h),需要全部重新创建。
重点说明 mas_updateConstraints
mas_updateConstraints 使用场景是,某个视图之前已经有 x,y,w,h 约束了。
现在因为某些原因,需要修改某个约束。
比如修改位置 x, y。
修改宽高 w,h。
但是,mas_updateConstraints 是一直都有效的吗?
场景一
两个 view。橙色的 view,是父视图。
紫色的 view 是子视图。
UIView *testView = [[UIView alloc] init];
testView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:testView];
[testView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.offset(20);
make.height.width.offset(200);
}];
_testView = testView;
UIView *test2View = [[UIView alloc] init];
test2View.backgroundColor = [UIColor purpleColor];
[testView addSubview:test2View];
[test2View mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.offset(20); // x,y 依赖于父容器
make.height.offset(100); // width 和父容器没有一毛钱关系
make.width.offset(100); // height 和父容器没有一毛钱关系
}];
_testView2 = test2View;
testView2 是子容器,约束设置的条件是 ,除了 x,y 和父容器有关系之外(也不可能没有关系)
width & height 都写的是常量,和父容器没有任何关系。
在 touchesBegan 测试 mas_updateConstraints,来修改 testView2 的 width,height。
(这个宽高和父容器没有一毛钱关系)
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[_testView2 mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.offset(150);
make.height.offset(150);
}];
}
运行结果:
15295690812429.jpg查看控制台,非常干净,没有报约束冲突的问题。
15295691064947.jpg场景二
还是两个 view。橙色的 view,是父视图。
紫色的 view 是子视图。
testView.backgroundColor = [UIColor orangeColor];
[self.view addSubview:testView];
[testView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.offset(20);
make.height.width.offset(200);
}];
_testView = testView;
UIView *test2View = [[UIView alloc] init];
test2View.backgroundColor = [UIColor purpleColor];
[testView addSubview:test2View];
[test2View mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.offset(20); // x,y 依赖于父容器
make.height.equalTo(testView).multipliedBy(0.5);// width 和父容器有关系了,它是父容器宽度的一半
make.width.equalTo(testView).multipliedBy(0.5); // height 和父容器有关系了,它是父容器高度的一半
// make.height.offset(100); // width 和父容器没有一毛钱关系
// make.width.offset(100); // height 和父容器没有一毛钱关系
}];
_testView2 = test2View;
现在 testView2 的 width
& height
也是约束设置的,但是已经和父容器建立关系了。
它们分别是父容器宽高的一半。
现在在使用 mas_updateConstraints 来更新testView2的宽高约束。
[_testView2 mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.offset(150);
make.height.offset(150);
}];
运行结果:
15295693759982.jpgtestVIew2使用mas_updateConstraints 并没有成功的修改自己的宽高(因为和父容器建立了关系了)
在来看看控制台输出:
15295694471885.jpg很不幸的是,控制台报出了约束异常。
mas_updateConstraints 好像,并不是万能的?
不是一句简单的 更新视图的约束就能说明白的。
那如何去修正呢?
修正步骤:
- 记录和父容器产生了关系的约束对象。
- 更新这些约束对象之前,先把之前的约束对象卸载。
声明两个约束对象,width & height
MASConstraint *_heightConstraint; // 子视图宽度约束
MASConstraint *_widthConstraint; // 子视图高度约束
记录和父容器产生了关系的约束对象
_heightConstraint = make.height.equalTo(testView).multipliedBy(0.5);
_widthConstraint = make.width.equalTo(testView).multipliedBy(0.5);
在更新这些和父视图建立了关系的约束之前,必须先卸载之前的约束对象。
然后再使用 mas_updateConstraints 更新全新的约束
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[_widthConstraint uninstall]; // 先卸载之前的宽度约束(multipliedBy)
[_heightConstraint uninstall]; // 先卸载之前的高度约束(multipliedBy)
[_testView2 mas_updateConstraints:^(MASConstraintMaker *make) {
make.width.offset(150);
make.height.offset(150);
}];
}
运行结果:
15295698322527.jpg再看看看控制台:
15295698660922.jpg非常干净。没有报任何冲突。
当然还有 centerX,centerY 位置相关的(x,y不冲突,不代表 centerX,centerY 不冲突)等约束,大家可以自己做测试看看。
最后结论:
- mas_updateConstraints 并是一个简单的更新视图约束就能说明白的。
- 某些和父亲容器建立了约束关系的约束,在使用 mas_updateConstraints 之前,必须先卸载之前的约束。
- 对于子视图的 x,y 约束,使用mas_updateConstraints,总是有效的。(有人会说,x,y 也和父视图建立了关系了呀?那你能找一个 x,y 和父视图没有建立关系的约束吗?)
- 对于父视图是控制器根 view 的情况下,mas_updateConstraints。这是因为根 view 的大小基本都是定死的。
- 当使用mas_updateConstraints遇到约束问题时,可以先想想,是哪些约束事先需要删除但没有删除的?
一个比较暴力的解决 在使用 mas_updateConstraints 出现约束冲突的问题方法。
更新哪个约束出冲突了,就把哪个约束删除了,在更新。也省的去研究,为什么会出冲突了。
约束本身就是个比较蛋疼的东西。
网友评论