NSLayoutConstraint的创建和删除
需要通过创建新的约束并且移除旧的约束来实现效果。在iOS8之前这个工作无疑是繁杂的,我们需要通过
- (void)addConstraint:(NSLayoutConstraint *)constraint;
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints;
- (void)removeConstraint:(NSLayoutConstraint *)constraint;
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints;
但在iOS8之后,NSLayoutConstraint提供了active的BOOL类型的变量供我们提供设置约束是否有效,这个值设置NO的时候约束就失效。同样我们创建了一个约束对象之后只需要设置active为YES之后就会自动生效了。
PS:你还要记住的是当一个约束的active属性被设为NO之后,即便我们重新将其激活,这个约束依旧是无效的,必须重新创建。
关于约束的计算公式以及这些计算的变量在NSLayoutConstraint对象中代表的属性:
根据这个公式假设我现在要给当前视图上的一个按钮添加水平居中的约束,那么约束的创建代码如下:
NSLayoutConstraint * centerXConstraint = [NSLayoutConstraint
constraintWithItem: _button //firstItem
attribute: NSLayoutAttributeCenterX //firstAttribute
relatedBy: NSLayoutRelationEqual //relation
toItem: _button.superview //secondItem
attribute: NSLayoutAttributeCenterX //secondAttribute
multiplier: 1.0 //multiplier
constant: 0]; //constant
删除NSLayoutConstraint
可以直接通过判断约束双方对象以及约束的属性类型来获取对应的约束并使其无效:
[_signInButton.constraints enumerateObjectsWithOptions: NSEnumerationReverse usingBlock: ^(__kindof NSLayoutConstraint * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (obj.firstItem == _signInButton && obj.firstAttribute == NSLayoutAttributeCenterX) {
obj.active = NO;
} else if (obj.firstAttribute == NSLayoutAttributeWidth && obj.secondAttribute == NSLayoutAttributeHeight) {
obj.active = NO;
}
}];
这段代码就等同于上面的
_loginCenterXConstraint.active = NO;
_loginRatioConstraint.active = NO;
虽然使用代码移除约束的方式更加复杂,但是在我们封装控件的时候,总是有可能用到的,所以这也是我们需要掌握的技巧。当然了,这种判断的方式也确实过于麻烦,NSLayoutConstraint还提供了类型为字符串identifier属性帮助我们识别约束。在故事板中我们可以通过右侧的属性栏直接看到该属性并且进行设置:
约束Identifier.png
这样上面的判断代码就可以简化成简单的判断id:
[_signInButton.constraints enumerateObjectsWithOptions: NSEnumerationReverse usingBlock: ^(__kindof NSLayoutConstraint * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj.identifier isEqualToString: @"loginIdentifier"]) {
obj.active = NO;
}
}];
尾言
简单做的笔记,有不足之处请见谅