Masonry就不做過多的介紹了,搞iOS布局的應該都知道這個開源庫,使用它能節省不少體力,最近在項目中使用這個庫的mas_updateConstraints時,發現該方法和自己想象的有點不一樣。先貼下自己的代碼:
# BaseClass [_textLabel mas_makeConstraints:^(MASConstraintMaker *make) { self.textLabelLeftLayout = make.left.equalTo(self.checkedButton.mas_right); make.centerY.equalTo(self.mas_centerY); make.height.mas_equalTo(checkBoxWidth); make.right.lessThanOrEqualTo(self.mas_right); }];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
這是基類里對textlabel的布局,其相對view本身居中顯示,而子類里想改變這種布局方式,改成和另外一個button對齊顯示,因此我就在子類里調整布局如下:
# SubClass [self.textLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.checkedButton.mas_centerY); }];
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
本以為這么做Masonry會幫我把centerY的布局更新,但是編譯運行時會提示存在沖突,有兩個centerY布局約束,不知道該使用哪一個,然后我就讀了下Masonry的源碼,發現原來mas_updateConstraints方法里對同一個布局的理解就是相對的元素也是一致才行,即這里這樣做才算一次update:
# SubClass [self.textLabel mas_updateConstraints:^(MASConstraintMaker *make) { make.centerY.equalTo(self.mas_centerY).offset(10); }];
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
所以,這里的一個update是針對如下這種情形才行:
A->B A->B的變化
A->C 這里是一個新的約束
源碼里有個方法是對是否是同一個約束的判斷:
- (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. 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; }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
可以看到,需要firstItem,secondItem,firstAttribute,secondAttribute,relation,multiplier,priority等一致才會當做同一個約束,否則都不算做一個約束。所以在使用mas_updateConstraints時大家一定要分清楚是否update還是重新添加了一個約束。
PS:針對我遇到的這種使用情況,我在基類里將我的居中約束設置了一個優先級來處理的
# BaseClass [_textLabel mas_makeConstraints:^(MASConstraintMaker *make) { self.textLabelLeftLayout = make.left.equalTo(self.checkedButton.mas_right); make.centerY.equalTo(self.mas_centerY).priorityMedium(); make.height.mas_equalTo(checkBoxWidth); make.right.lessThanOrEqualTo(self.mas_right); }];
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 頂
- 2
