最近在學習Masonry在更新約束動畫過程中產(chǎn)生了一些疑問:setNeedsLayout滨嘱、layoutIfNeeded和setNeedsUpdateConstraints、updateConstraintsIfNeeded的區(qū)別和聯(lián)系浸间。
通過查看前輩的文章和實踐個人理解如下:
-setNeedsLayout方法: 標記為需要重新布局太雨,異步調(diào)用layoutIfNeeded刷新布局,不立即刷新魁蒜,但layoutSubviews一定會被調(diào)用
-layoutIfNeeded方法:如果囊扳,有需要刷新的標記吩翻,立即調(diào)用layoutSubviews進行布局(如果沒有標記,不會調(diào)用layoutSubviews)
-setNeedsUpdateConstraints方法: 標記為需要更新約束锥咸,異步調(diào)用updateViewConstraints刷新布局狭瞎,不立即刷新,但updateViewConstraints一定會被調(diào)用
-updateConstraintsIfNeeded方法:如果搏予,有需要刷新的約束脚作,立即調(diào)用updateViewConstraints進行布局(如果沒有標記,不一定會調(diào)用layoutSubviews)
舉個栗子:
//
// ViewController.m
// PodDome
//
// Created by ZX on 2017/2/13.
// Copyright ? 2017年 ZX. All rights reserved.
//
#import "ViewController.h"
// 只要添加了這個宏缔刹,就不用帶mas_前綴
#define MAS_SHORTHAND
// 只要添加了這個宏球涛,equalTo就等價于mas_equalTo
#define MAS_SHORTHAND_GLOBALS
// 這個頭文件一定要放在上面兩個宏的后面
#import "Masonry.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *growingButton;
@property (nonatomic, assign) CGFloat scacle;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.growingButton = [UIButton buttonWithType:UIButtonTypeSystem];
[self.growingButton setTitle:@"點我放大" forState:UIControlStateNormal];
self.growingButton.layer.borderColor = UIColor.greenColor.CGColor;
self.growingButton.layer.borderWidth = 3;
[self.growingButton addTarget:self action:@selector(onGrowButtonTaped:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.growingButton];
self.scacle = 1.0;
[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.view);
// 初始寬、高為100校镐,優(yōu)先級最低
make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
// 最大放大到整個view
make.width.height.lessThanOrEqualTo(self.view);
}];
}
#pragma mark - updateViewConstraints
- (void)updateViewConstraints {
[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.view);
// 初始寬亿扁、高為100,優(yōu)先級最低
make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
// 最大放大到整個view
make.width.height.lessThanOrEqualTo(self.view);
}];
[super updateViewConstraints];
}
- (void)onGrowButtonTaped:(UIButton *)sender {
self.scacle += 0.5;
// 告訴self.view約束需要更新
// [self.view setNeedsUpdateConstraints];
// 調(diào)用此方法告訴self.view檢測是否需要更新約束鸟廓,若需要則更新从祝,下面添加動畫效果才起作用
// [self.view updateConstraintsIfNeeded];
// 告訴self.view布局需要更新
[self.view setNeedsLayout];
// 調(diào)用此方法告訴self.view檢測是否需要更新布局,若需要則更新引谜,下面添加動畫效果才起作用
[self.view layoutIfNeeded];
[UIView animateWithDuration:0.3 animations:^{
[self.view layoutIfNeeded];
}];
}
- (void)viewDidLayoutSubviews {
[self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self.view);
// 初始寬牍陌、高為100,優(yōu)先級最低
make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
// 最大放大到整個view
make.width.height.lessThanOrEqualTo(self.view);
}];
[super viewDidLayoutSubviews];
}
@end
不管約束更新的代碼是放在layoutIfNeeded 還是 updateViewConstraints 都能完成約束更新的動畫效果员咽。
補充一點:在控制器中viewDidLayoutSubviews 等價于 layoutSubviews毒涧。