This question comes at a good time! I literally JUST solved this same issue myself.
- Create a
UIView
(let’s refer to it asmainBackground
) inside your cell’s Content View. This will contain all of your cell’s content. Position it and apply necessary constraints in the Storyboard. - Create another
UIView
. This one will be the one with the shadow (let’s refer to it asshadowLayer
). Position it exactly as you didmainBackground
, but behind it, and apply the same constraints. -
Now you should be able to set the rounded corners and the shadows as follows:
cell.mainBackground.layer.cornerRadius = 8 cell.mainBackground.layer.masksToBounds = true cell.shadowLayer.layer.masksToBounds = false cell.shadowLayer.layer.shadowOffset = CGSizeMake(0, 0) cell.shadowLayer.layer.shadowColor = UIColor.blackColor().CGColor cell.shadowLayer.layer.shadowOpacity = 0.23 cell.shadowLayer.layer.shadowRadius = 4
However, the problem here is: calculating the shadow for every single cell is a slow task. You’ll notice some serious lag when you scroll through your table. The best way to fix this is to define a UIBezierPath
for the shadow, then rasterize it. So you may want to do this:
cell.shadowLayer.layer.shadowPath = UIBezierPath(roundedRect: cell.shadowLayer.bounds, byRoundingCorners: .AllCorners, cornerRadii: CGSize(width: 8, height: 8)).CGPath
cell.shadowLayer.layer.shouldRasterize = true
cell.shadowLayer.layer.rasterizationScale = UIScreen.mainScreen().scale
But this creates a new problem! The shape of the UIBezierPath
depends on shadowLayer
‘s bounds, but the bounds are not properly set by the time cellForRowAtIndexPath
is called. So, you need to adjust the shadowPath
based on shadowLayer
‘s bounds. The best way to do this is to subclass UIView
, and add a property observer to the bounds property. Then set all the properties for the shadow in didSet
. Remember to change the class of your shadowLayer
in the storyboard to match your new subclass.
class ShadowView: UIView {
override var bounds: CGRect {
didSet {
setupShadow()
}
}
private func setupShadow() {
self.layer.cornerRadius = 8
self.layer.shadowOffset = CGSize(width: 0, height: 3)
self.layer.shadowRadius = 3
self.layer.shadowOpacity = 0.3
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: 8, height: 8)).cgPath
self.layer.shouldRasterize = true
self.layer.rasterizationScale = UIScreen.main.scale
}
}