那些年我们一起追过的自动布局Masonry(一)requiresConstraintBasedLayout

来源:互联网 发布:经典sql语句面试题 编辑:程序博客网 时间:2024/06/10 04:39

目前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,assign) CGSize buttonSize;


@end


@implementation MASExampleUpdateView


- (id)init {

    self = [superinit];

    if (!self)return nil;


    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
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


原创粉丝点击