7

I have a NSImageView and want to add a shadow. I've tried doing it programmatically with:

NSShadow *shadow = [[[NSShadow alloc] init] autorelease];
[shadow setShadowBlurRadius:4.0f];
[shadow setShadowOffset:CGSizeMake(4.0f, 4.0f)];
[shadow setShadowColor:[NSColor blackColor]];

[view setShadow:shadow];

But it won't appear. Any ideas? Thanks.

Kevin Sylvestre
  • 37,288
  • 33
  • 152
  • 232
  • You could try creating an empty NSImage (of the same size as the one you want to draw), `lockFocus` on it, set the shadow, and draw the original into the new one (and `unlockFocus`). I use that technique for tinting images; can't guarantee it'll work for shadow. – Richard Jan 24 '11 at 21:13

2 Answers2

10

You have to set the parameters of the shadow. By default, it's all zeroes, so it has no visible effect on a view.

See -setShadowColor:, -setShadowRadius:, and -setShadowOffset: on NSShadow, I believe.

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • I tried adding all the above to no effect. I updated the above sample. – Kevin Sylvestre Jan 24 '11 at 20:57
  • 3
    Is your view also backed by a `CALayer`? If not, you must enable Core Animation backing by sending `setWantsLayer:` (with a value of `YES`) to your view before setting the shadow. – Jonathan Grynspan Jan 24 '11 at 21:16
  • @Jonathan: that was what I was about to post as an answer indeed. `setShadow:` simply copies the shadow's properties to the Core Animation layer, so the view must be backed by a `CALayer`. This is also noticeable when you want to apply a shadow to a view using Interface Builder. – Joost Jan 24 '11 at 21:21
  • Ayup. Have had my head in iOS for a while, so it briefly slipped my mind that on the Mac, views are not layer-backed by default. :) – Jonathan Grynspan Jan 24 '11 at 21:32
  • Any way to avoid clipping the shadow if once a CALayer is enabled? – Kevin Sylvestre Jan 24 '11 at 22:29
  • 1
    I believe if the superview is also layer-backed, the clipping rules change, but it has been a while. – Jonathan Grynspan Jan 24 '11 at 22:54
  • Not to sound crass, but to award a bounty, you must actively click the appropriate button in your UI. (Okay, that sounded crass anyway, didn't it?) – Jonathan Grynspan Jan 25 '11 at 02:33
  • @Jonathan Sorry! I tried to add it when I marked an answer but it required waiting a day (and then I forgot). My apologies! – Kevin Sylvestre Jan 28 '11 at 22:20
  • No worries. I just didn't want that precious precious rep to go to waste. Precious, delicious rep... – Jonathan Grynspan Jan 29 '11 at 00:08
2

Swift 4

let shadow = NSShadow()
shadow.shadowOffset = NSMakeSize(2, -2)
shadow.shadowColor = NSColor.lightGray
shadow.shadowBlurRadius = 3

imageView.wantsLayer = true
imageView.shadow = shadow
Confused Vorlon
  • 9,659
  • 3
  • 46
  • 49