解决xib、storyboard用自动布局(Auto Layout)使用UIBezierPath时出现位置错误的问题

Auto Layout使布局变得简单、方便、从iOS12开始变得更加高效,目前来看Auto Layout已经非常的完善了,简书一搜,一大堆的教程,各种花式的教程,我就不在这里贴出了,主要是解决一些关于Auto Layoutbug
今天说的是在使用Auto Layout布局完成以后,因为原型图图内有个虚线的边框,所以直接将view拖拽为属性,使用UIBezierPath进行代码编写,虚线很简单,代码如下:

/// 增加虚线
/// @param pDottedLine addview  原文虚线方法转自:https://www.jianshu.com/p/12b439443b3b
/// @param pStrokeColor 虚线的颜色
/// @param pFillColor 填充的颜色
/// @param pCornerRadius 设置圆角
- (void)addDottedLine:(UIView *)pDottedLine withStrokeColor:(CGColorRef)pStrokeColor withFillColor:(CGColorRef)pFillColor withCornerRadius:(CGFloat)pCornerRadius{
    CAShapeLayer *border = [CAShapeLayer layer];
      
       //虚线的颜色
       border.strokeColor = pStrokeColor;
       //填充的颜色
       border.fillColor = pFillColor;
       //要是设置圆角则 cornerRadius: x
       UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:pDottedLine.bounds cornerRadius:pCornerRadius];
       
       //设置路径
       border.path = path.CGPath;
       
       border.frame = pDottedLine.bounds;
       //虚线的宽度
       border.lineWidth = 1.f;
      
       //设置线条的样式
       //    border.lineCap = @"square";
       //虚线的间隔
       border.lineDashPattern = @[@4, @2];
       
       //self.lineButton.layer.cornerRadius = 5.f;
       //self.lineButton.layer.masksToBounds = YES;
       
       [pDottedLine.layer addSublayer:border];

}

但是在使用的时候发现设置的虚线运行的时候竟然仅仅是xibframe的大小,而Auto Layout并没有出现效果,在不同的设备上切换,发现了这一个bug,除非将此方法放到viewDidAppear:方法内,但是放到viewDidAppear:根据控制器的生命周期来看,会出现闪烁,原因也是很简单,因为在viewDidAppear:UI已经完成,再要使用UIBezierPath肯定会出现闪烁,后来想Auto Layout应该是有一个立即更新UI的方法,后来看UIView的头文件,发现了setNeedsLayoutlayoutIfNeeded这2个方法,api中如下:

// Allows you to perform layout before the drawing cycle happens. -layoutIfNeeded forces layout early
- (void)setNeedsLayout;
- (void)layoutIfNeeded;

又在 stackoverflow 中找到了更加详细的说明,故在使用Auto Layout布局时,要有后期使用代码修改UI的时候,要先调用layoutIfNeeded方法。在进行修改UI则运行以后就会遵守Auto Layout了,不会出现在不同设备上出现偏移的问题,当然在切圆角时也发现了同样的问题,提前调用layoutIfNeeded在进行切圆角,即[self.xxx layoutIfNeeded];即可。

本文引用如下文章:

stackoverflow - How is layoutIfNeeded used?

setNeedsLayout和layoutIfNeeded看我就懂!

bug效果图如下:

没有使用 layoutIfNeeded 的布局.png
使用 layoutIfNeeded 的布局.png

推荐阅读更多精彩内容