Masonry中setNeedsLayout、layoutIfNeeded和setNeedsUpdateConstraints、updateConstraintsIfNeeded的区别和联系

最近在学习Masonry在更新约束动画过程中产生了一些疑问:setNeedsLayout、layoutIfNeeded和setNeedsUpdateConstraints、updateConstraintsIfNeeded的区别和联系。
通过查看前辈的文章和实践个人理解如下:

-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用

-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

-setNeedsUpdateConstraints方法: 标记为需要更新约束,异步调用updateViewConstraints刷新布局,不立即刷新,但updateViewConstraints一定会被调用

-updateConstraintsIfNeeded方法:如果,有需要刷新的约束,立即调用updateViewConstraints进行布局(如果没有标记,不一定会调用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,优先级最低
        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,优先级最低
        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];
      // 调用此方法告诉self.view检测是否需要更新约束,若需要则更新,下面添加动画效果才起作用
//    [self.view updateConstraintsIfNeeded];
    
      // 告诉self.view布局需要更新
       [self.view setNeedsLayout];
      // 调用此方法告诉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,优先级最低
        make.width.height.mas_equalTo(100 * self.scacle).priorityLow();
        // 最大放大到整个view
        make.width.height.lessThanOrEqualTo(self.view);
    }];

    
    [super viewDidLayoutSubviews];
}
@end

不管约束更新的代码是放在layoutIfNeeded 还是 updateViewConstraints 都能完成约束更新的动画效果。

补充一点:在控制器中viewDidLayoutSubviews 等价于 layoutSubviews。

你可能感兴趣的:(Masonry中setNeedsLayout、layoutIfNeeded和setNeedsUpdateConstraints、updateConstraintsIfNeeded的区别和联系)