那些年我們一起追過的自動佈局Masonry(一)requiresConstraintBasedLayout
目前iOS開發中大多數頁面都已經開始使用Interface Builder的方式進行UI開發了,但是在一些變化比較複雜的頁面,還是需要通過程式碼來進行UI開發的。而且有很多比較老的專案,本身就還在採用純程式碼的方式進行開發。
而現在iPhone和iPad螢幕尺寸越來越多,雖然開發者只需要根據螢幕點進行開發,而不需要基於畫素點進行UI開發。但如果在專案中根據不同螢幕尺寸進行各種判斷,寫死座標的話,這樣開發起來是很吃力的。
所以一般用純程式碼開發UI的話,一般都是配合一些自動化佈局的框架進行螢幕適配。蘋果為我們提供的適配框架有:VFL、UIViewAutoresizing、Auto Layout、Size Classes等。
其中Auto Layout是使用頻率最高的佈局框架,但是其也有弊端。就是在使用UILayoutConstraint的時候,會發現程式碼量很多,而且大多都是重複性的程式碼,以至於好多人都不想用這個框架。
後來Github上的出現了基於UILayoutConstraint封裝的第三方佈局框架Masonry,Masonry使用起來非常方便。
什麼是Masonry
Masonry是一個對系統NSLayoutConstraint進行封裝的第三方自動佈局框架,採用鏈式程式設計的方式提供給開發者API。系統AutoLayout支援的操作,Masonry都支援,相比系統API功能來說,Masonry是有過之而無不及。
Masonry採取了鏈式程式設計的方式,程式碼理解起來非常清晰易懂,而且寫完之後程式碼量看起來非常少。之前用NSLayoutConstraint寫很多程式碼才能實現的佈局,用Masonry最少一行程式碼就可以搞定。
現在我們以Masonry中的UpdateConstraints為例,講解一下
#import "MASExampleUpdateView.h"
@interface MASExampleUpdateView ()
@property (nonatomic, strong) UIButton *growingButton;
@property (nonatomic
@end
@implementation MASExampleUpdateView
- (id)init {
self = [superinit];
if (!self) returnnil;
self.growingButton = [UIButtonbuttonWithType:UIButtonTypeSystem];
[self.growingButtonsetTitle:@"Grow Me!"forState:UIControlStateNormal];
self.growingButton.layer.borderColor = UIColor.greenColor.CGColor;
self.growingButton.layer.borderWidth = 3;
[self.growingButtonaddTarget:selfaction:@selector(didTapGrowButton:) forControlEvents:UIControlEventTouchUpInside];
[selfaddSubview:self.growingButton];
self.buttonSize = CGSizeMake(100, 100);
returnself;
}
+ (BOOL)requiresConstraintBasedLayout
{
returnYES;
}
// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {
[self.growingButtonupdateConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self);
make.width.equalTo(@(self.buttonSize.width)).priorityLow();
make.height.equalTo(@(self.buttonSize.height)).priorityLow();
make.width.lessThanOrEqualTo(self);
make.height.lessThanOrEqualTo(self);
}];
//according to apple super should be called at end of method
[superupdateConstraints];
}
- (void)didTapGrowButton:(UIButton *)button {
self.buttonSize = CGSizeMake(self.buttonSize.width * 1.3, self.buttonSize.height * 1.3);
// tell constraints they need updating標記需要重新進行佈局
[selfsetNeedsUpdateConstraints];
// update constraints now so we can animate the change呼叫此方法,如果標記為有需要重新佈局的約束,則立即進行重新佈局,內部會呼叫updateConstraints.
[selfupdateConstraintsIfNeeded];
//佈局
[UIViewanimateWithDuration:0.4animations:^{
[selflayoutIfNeeded];
}];
}
看到很多Autolayout寫的自定義控制元件中都實現了requiresConstraintBasedLayout
方法,一直不知道這個方法有什麼用,因為不實現這個方法也沒發現有什麼影響。經過查詢資料,有解釋如下:constraint-based layout engages lazily when someone tries to use it (e.g., adds a constraint to a view). If you do all of your constraint set up in -updateConstraints, you might never even receive updateConstraints if no one makes a constraint. To fix this chicken and egg problem, override this method to return YES if your view needs the window to use constraint-based layout.
意思就是基於約束的佈局是懶觸發的,只有在添加了約束的情況下,系統才會自動呼叫updateConstraints方法,如果把所有的約束放在 updateConstraints中,那麼系統將會不知道你的佈局方式是基於約束的,所以重寫requiresConstraintBasedLayout 返回YES就是明確告訴系統:雖然我之前沒有新增約束,但我確實是基於約束的佈局!這樣可以保證系統一定會呼叫 updateConstraints 方法 從而正確新增約束.
連結:http://www.jianshu.com/p/b58233a2c640
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。