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;
}
}];
尾言
簡單做的筆記,有不足之處請見諒