Masonry框架初次使用遇到的坑 frame为0

 

实现自适应布局的一个非常方便的方法就是使用Masonry框架,然而使用Masonry布局的时候,并不能立刻反应到frame的改变上,比如:

UIView *parent = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
UIImageView *child = [UIView alloc] init];
[parent addSubview:child];
[child mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(20,20));
        make.top.left.mas_equalTo(50);
    }];
NSLog(@"%@",redView);

打印结果:
** <UIImageView: 0x7fb222605550; frame = (0 0; 0 0); layer = <CALayer: 0x7fb22260b3a0>>**

可以发现,虽然使用Masonry进行布局和约束,但是子视图childframe仍然为(0, 0, 0 ,0). 

而这时候如果有需求要设置child的形状为圆形,就得知道它的frame,像下面这样写肯定不会设置成功的:

[child mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(20,20));
        make.top.left.mas_equalTo(50);
    }];
 child.layer.cornerRadius = child.bounds.size.width/2;
 child.layer.masksToBounds = YES; //设置头像为圆形

因为这时候的frame还是0。我想会不会是因为block中的处理是放在另一个线程中异步进行的,block还没执行完就已经走到了下面使用frame的代码,(一阵狂喜,好聪明。。。),所以马上把代码改写:

[child mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.mas_equalTo(CGSizeMake(20,20));
        make.top.left.mas_equalTo(50);
        child.layer.cornerRadius = child.bounds.size.width/2;
        child.layer.masksToBounds = YES; //设置头像为圆形
    }];

然而并没有什么卵用。。。

没办法只能问谷歌了,然后找到了Masonry约束下获取frame的方法:

使用masonry的实质还是调用了ios7以后的autolayout,如果要更新frame,需要调用layoutIfNeeded函数进行布局,然后所约束的控件才会按照约束条件,生成当前布局相应的framebounds。这样就可以利用这两个属性来进行图片圆角剪裁。而调用layoutIfNeeded的目的是让系统调用layoutSubviews方法,我们也可以直接在这个方法里获取frame,因为这时候开始layout subviews,Masonry已经计算出了真实的frame。

下面附上关于autolayout更新几个方法的区别:

setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。

layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点,动画可以在更新布局后直接使用这个方法让动画生效。

layoutSubviews:系统重写布局

setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始

updateConstraintsIfNeeded:告知立刻更新约束

updateConstraints:系统更新约束

原文地址:https://www.cnblogs.com/yecong/p/6876813.html