Search code examples
iosswiftscrollviewshadow

Why is my shadow layer not positioned correctly?


I got a custom subclass of UIView called RoundedView:

import UIKit

@IBDesignable
class RoundedView: UIView {

    @IBInspectable var shadowColor : UIColor? {
        didSet {
            layer.shadowColor = shadowColor?.cgColor
            layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
        }
    }

    @IBInspectable var shadowOffset : CGSize = CGSize(width: 20, height: 20) {
        didSet {
            layer.shadowOffset = shadowOffset
            layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
        }
    }

    @IBInspectable var shadowRadius : CGFloat = 0.0 {
        didSet {
            layer.shadowRadius = shadowRadius
            layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
        }
    }

    @IBInspectable var shadowOpacity : Float = 1.0 {
        didSet {
            layer.shadowOpacity = shadowOpacity
            layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
        }
    }


}

With this class, I want to be able to set the shadow for a view by using the Xcode Interface Builder. Unfortunately, the behavior is pretty strange; when setting the color to blue, the offset to CGSize.zero, the radius to 0 and the opacity to 1, the whole shadow is moved to the right:

This is the output of 1. the shadowPath, 2. the bounds and 3. the frame:

shadowPath: 
    Path 0x60800022e040:
      moveto (0, 0)
        lineto (300, 0)
        lineto (300, 150)
        lineto (0, 150)
        closepath
self.bounds: 
    (0.0, 0.0, 300.0, 150.0)
self.frame: 
    (37.0, 268.5, 300.0, 150.0)

I have no idea why this is happening. Could you help me out?


Solution

  • I cannot simply put this line

    layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
    

    into every didSet observer as the frame may still change.

    Solved by overriding the function layoutSubviews and adding the line there.