13

I have gone through many threads here and other blogs but not able to solve this issue. I have a added a subview in content view of window. Here is the storyboard--

enter image description here-

I have dragged out outlet of customView to view controller and here is the code for view controller -

import Cocoa
import QuartzCore

class ViewController: NSViewController {

    @IBOutlet weak var customView: NSView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.wantsLayer = true
        self.customView.wantsLayer = true
        self.customView.layer?.backgroundColor = NSColor.redColor().CGColor
        self.customView.layer?.cornerRadius = 5.0
        self.customView.layer?.shadowOpacity = 1.0
        self.customView.layer?.shadowColor = NSColor.blackColor().CGColor
        self.customView.layer?.shadowOffset = NSMakeSize(0, -3)
        self.customView.layer?.shadowRadius = 20
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }
}

I have added QuartzCore frame work in my project - enter image description here

But the shadow is not appearing, here is the screen shot - enter image description here.

I am not able to solve what appears to be trivial. What am I missing? thanks for your help.

Abhishek
  • 852
  • 9
  • 24

3 Answers3

37

If I add the following line it solves the problem-

self.customView.shadow = NSShadow()

Final code is -

import Cocoa
import QuartzCore

class ViewController: NSViewController {

    @IBOutlet weak var customView: NSView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.wantsLayer = true
        self.view.superview?.wantsLayer = true
        self.customView.wantsLayer = true
        self.customView.shadow = NSShadow()
        self.customView.layer?.backgroundColor = NSColor.redColor().CGColor
        self.customView.layer?.cornerRadius = 5.0
        self.customView.layer?.shadowOpacity = 1.0
        self.customView.layer?.shadowColor = NSColor.greenColor().CGColor
        self.customView.layer?.shadowOffset = NSMakeSize(0, 0)
        self.customView.layer?.shadowRadius = 20
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }


}

I am not able to identify the issue may be someone here will point it out.

duan
  • 8,515
  • 3
  • 48
  • 70
Abhishek
  • 852
  • 9
  • 24
  • 5
    The NSShadow() is the key. Next the hosting view (e.g. superview) needs wantsLayer to true. – Benny Khoo Dec 25 '16 at 09:30
  • In the Core Animation Programming guide, it says some layer properties should not be directly modified for layer backed view in OS X. In this list of properties are shadowOffset, shadowColor, shadowRadius, shadowOpacity. https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html So it is better to create a shadow object, set the properties on this object and then assign it to the layer's shadow. – RookiePro Apr 07 '17 at 14:25
  • in my case the NSShadow invalidates the layer cornerRadius – the Reverend Apr 29 '19 at 23:42
  • This helped me! I just had to set wantsLayer to true – Anthony Gedeon Jan 09 '21 at 04:31
0

I added code like below to get shadow to NSView. It worked For me.

     @IBOutlet weak var leftCustomBgView: NSView!
    
     override func viewDidAppear() {
        super.viewDidAppear()
        initialSetUp()
     }

    fileprivate func initialSetUp() {
        self.leftCustomBgView.wantsLayer = true
        self.leftCustomBgView.shadow = NSShadow()
        self.leftCustomBgView.layer?.backgroundColor = NSColor.white.cgColor
        self.leftCustomBgView.layer?.cornerRadius = 6
        self.leftCustomBgView.layer?.shadowColor = NSColor.black.cgColor
        self.leftCustomBgView.layer?.shadowOpacity = 1.0
        self.leftCustomBgView.layer?.shadowOffset = CGSize(width: 0, height: 0)
        self.leftCustomBgView.layer?.shadowRadius = 6
    }

--------------- OR -----------------

self.leftCustomBgView.addShadow(customViewBgColor: NSColor.white,
                                    customViewRadius: 6,
                                    shadowViewColor: NSColor.black,
                                    shadowViewRadius: 6,
                                    opacity: 1.0)

extension NSView {
//Add Shadow to NSView
func addShadow(customViewBgColor: NSColor, customViewRadius: CGFloat, shadowViewColor: NSColor, shadowViewRadius: CGFloat, opacity: Float) {
    self.wantsLayer = true
    self.shadow = NSShadow()
    self.layer?.backgroundColor = customViewBgColor.cgColor
    self.layer?.cornerRadius = customViewRadius
    self.layer?.shadowColor = shadowViewColor.cgColor
    self.layer?.shadowOpacity = opacity
    self.layer?.shadowOffset = CGSize(width: 0, height: 0)
    self.layer?.shadowRadius = shadowViewRadius
 }
}
Mannam Brahmam
  • 2,225
  • 2
  • 24
  • 36
0

An alternative to the accepted answer, you can configure the NSShadow before assigning it.

The documentation says, as some folks have already pointed out:

If the view does not have a layer, setting the value of this property has no effect.

Example

let shadow = NSShadow()
shadow.shadowColor = .red
shadow.shadowBlurRadius = 20
        
let view = NSView()
view.wantsLayer = true
view.shadow = shadow
vicegax
  • 4,709
  • 28
  • 37