1.为什么Masonry中的block 访问外部变量不需要__weak?
2.遇到的坑 frame为0
答案1:具体原因可以参考cocoaChina上面的这篇文章(Block到底什么时候用weakSelf)http://blog.cocoachina.com/article/58103 太长,就不拷贝到这里了.
答案2:(来自cocoachina)
这个就和网络请求里面使用self道理是一样的。因为UIView未强持有block,所以这个block只是个栈block,而且构不成循环引用的条件。栈block有个特性就是它执行完毕之后就出栈,出栈了就会被释放掉。看mas_makexxx的方法实现会发现这个block很快就被调用了,完事儿就出栈销毁,构不成循环引用,所以可以直接放心的使用self。
//而且这个block里面用weakSelf还有可能会出问题,因为mas_qeual如果得到一个nil参数的话应该会导致程序崩溃。
//上面这行注掉,因为之前想的是在mas_makexxx的block执行的时候self被释放可能会导致equal得到一个为nil的参数,将导致crash
//但是后来想想这种情况根本不会出现,因为这个block不执行完就不会出栈,不会出栈self就不会释放,所以,上面说的情况不存在
//固定间隙,内部跟随外部变化.
[bigImageV mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.left.bottom.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(0, 0, 0, 0));
}];
//设置控件位置
[onDutyButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.size.mas_equalTo(CGSizeMake(370/2, 60));// green大小
make.bottom.mas_equalTo(-60);
make.centerX.mas_equalTo(bigImageV.mas_centerX);
}];
//设置比例 imageview跟随系统宽度,保持宽高比,自动调节高度.
UIImageView *bottomImageView = [[UIImageView alloc]init];
bottomImageView.image = [UIImage imageNamed:@"底部曲线"];
[self.view addSubview:bottomImageView];
[bottomImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.view);
make.width.equalTo(self.view);
make.height.equalTo(bottomImageView.mas_width).multipliedBy(0.1147);// 高/宽 == 0.6
}];
//设置循环创建的button 宽度为75固定值(withFixedItemLength)
//设置第一个button 距离 view左侧的距离是25(leadSpacing)
//设置最后第一个button 距离 view右侧的距离是68(tailSpacing)
注意:创建button之前,最好把button放到一个干净的view上面.上面什么都没有,只有要计算的控件.并且这个干净的view的fram 在button add到上面之前要已经计算好了自己的frame
[_buttonArray mas_distributeViewsAlongAxis:MASAxisTypeHorizontal
withFixedItemLength:75 leadSpacing:25 tailSpacing:68];
[_buttonArray mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_top);
make.height.equalTo(@40);
}];
//跟上面的对比理解, withFixedSpacing,即,固定的间隔(这里设置的间隔是0),控件的长度是均分的.
//leadSpacing tailSpacing 跟上面相同;注意事项也相同.
[array mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:0 leadSpacing:0 tailSpacing:0];
[array mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(theViewwww.mas_centerY);
make.height.equalTo(@45);
}];
2.遇到的坑 frame 为0
使用masonry的实质还是调用了ios7以后的autolayout,如果要更新frame,需要调用layoutIfNeeded函数进行布局,然后所约束的控件才会按照约束条件,生成当前布局相应的frame和bounds。这样就可以利用这两个属性来进行图片圆角剪裁。而调用layoutIfNeeded的目的是让系统调用layoutSubviews方法,我们也可以直接在这个方法里获取frame,因为这时候开始layout subviews,Masonry已经计算出了真实的frame。
下面附上关于autolayout更新几个方法的区别:
setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点,动画可以在更新布局后直接使用这个方法让动画生效。
layoutSubviews:系统重写布局
setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始
updateConstraintsIfNeeded:告知立刻更新约束
updateConstraints:系统更新约束