0

Unfortunately it seems that setting the shadow attributes on the layer directly doesn't work:

let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
shadowView.wantsLayer = true
shadowView.layer!.backgroundColor = .white
shadowView.layer!.shadowRadius = 50
shadowView.layer!.shadowColor = .black
shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30)
shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil)

Setting the NSView.shadow property instead works:

let shadowView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))let shadow = NSShadow()
shadow.shadowBlurRadius = 50
shadow.shadowColor = .black
shadow.shadowOffset = CGSize(width: 0, height: -30)
shadowView.shadow = shadow
shadowView.wantsLayer = true
shadowView.layer!.backgroundColor = .white

But NSShadow doesn't support a custom path. What's the easiest way to set a shadow with a custom path?

3
  • This article: blog.prototypr.io/… --- scroll down to Shadow Performance ... is that what you're looking for? Commented Mar 15, 2023 at 21:16
  • Thank you, but that article also uses the CALayer.shadowPath property, which seems to work probably because the contents property is also being set at the same time to an image, and being able to use shadows for images only is quite limiting. Commented Mar 16, 2023 at 12:14
  • I don't think it has anything to do with images... see my answer. Commented Mar 16, 2023 at 20:53

1 Answer 1

1

Edited Answer - after comments...

The reason your shadow code didn't seem to work was because you were missing two property settings:

// need these two properties set
shadowView.layer!.masksToBounds = false
shadowView.layer!.shadowOpacity = 1.0

Quick example (I moved the shadowView origin to 100,100 so we can see the full shadow):

class ViewController: NSViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let shadowView = NSView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
        view.addSubview(shadowView)
        
        shadowView.wantsLayer = true
        
        shadowView.layer!.backgroundColor = .white
        shadowView.layer!.shadowRadius = 50
        shadowView.layer!.shadowColor = .black
        shadowView.layer!.shadowOffset = CGSize(width: 0, height: -30)
        shadowView.layer!.shadowPath = CGPath(roundedRect: shadowView.bounds, cornerWidth: 25, cornerHeight: 25, transform: nil)
        
        // need these two properties set
        shadowView.layer!.masksToBounds = false
        shadowView.layer!.shadowOpacity = 1.0  // set as desired
        
    }
    
}

Result:

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot for your extensive sample, but even here, you're creating the shadow not from the NSView itself but from another CALayer (the shapeLayer variable). The question remains why my code doesn't work and how one can make a view drop a shadow without doing all the drawing inside a layer.
@Nickkk - whoops... guess I misunderstood what you were looking for. See the Edit at the bottom of my answer.
Ah, the masksToBounds was the missing bit. (I had already tried shadowOpacity but forgot to include it in the sample.) Thanks a lot! (You may want to invert the two pieces so that the one answering the question comes at the top, or completely remove the first part.)
@Nickkk - edited my answer so it directly addresses your issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.