I need a shadow on my view. I tried using the view’s NSShadow
capability, but it is too slow to use in a scroll view. I want to try using the layer’s shadow properties to hopefully improve performance.
In my NSView.updateLayer()
method, I set the following properties:
layer.shadowOffset = CGSize(width: 0, height: -3)
layer.shadowRadius = 3
layer.shadowColor = NSColor.black().cgColor
layer.shadowOpacity = 0.3
No shadow is shown. I tried also setting NSView.wantsDefaultClipping
and CALayer.masksToBounds
to false
, but there is still no shadow.
Why is there no shadow when using the CALayer
shadow properties?
I looked at the disassembly of CALayer.render(in:)
and it looked like it was properly accessing the layer shadow properties. So NSView
probably overwrites the layer shadow properties with its own on every draw cycle. The bottom line is that you can only add shadows to view-backing layers by using the shadow
property on the view.
I did solve my scroll performance problem though. I profiled my app during a scroll and noticed that the creation of the shadow image in CGContextEndTransparencyLayer
was causing the CPU to spike.
There are two steps for creating a shadow. First, a path for the shadow has to be computed based on the alpha channel of the pixels above. Second, a gaussian blur is applied in order to soften the edges of the shadow.
Since I know the view on top of the shadow is fully opaque, I know the path will be simply the view’s bounds. I could have skipped the first step by setting the layer’s shadowPath
property. But unfortunately, the layer’s shadow properties are overridden by the view which doesn’t have a shadowPath
property.
My solution was to create a container view that draws a rectangular shadow image underneath the content view. This shadow image is created once and cached, increasing scroll performance dramatically. And thanks to the power of Auto Layout (specifically, the alignment rect insets), the container view can be used without having to manually adjust for the shadow.
You can view my code on GitHub.