Search code examples
iosswiftuiviewcalayer

Why do I need to call layoutIfNeeded() when adding a layer mask to a subview?


My main view has a subview, which I add a mask to using the following extension:

extension UIView{
func addTopRoundCorners(){
    let bezierPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [UIRectCorner.topLeft, UIRectCorner.topRight], cornerRadii: CGSize(width: 20, height: 20))
    let maskLayer = CAShapeLayer()
    maskLayer.path = bezierPath.cgPath
    maskLayer.fillColor = UIColor.red.cgColor
    self.layer.mask = maskLayer
}

}

I have notice the effects of this code on my subview only appears on screen if I call layoutIfNeeded() on my main view before adding the mask to my subview. I'd really appreciate if someone could explain to me why this is?


Solution

  • layoutIfNeeded will calculate position and size of your view. If you call your addTopRoundCorners() function before the final position and size is calculated, then self.bounds that is used to create UIBezierPath will be wrong.

    Auto layout will not automatically resize your mask layer, and will not call addTopRoundCorners to recreate the path.