07-18-2023, 09:51 PM
This question comes at a good time! I literally JUST solved this same issue myself.
1. Create a <code>UIView</code> (let's refer to it as <code>mainBackground</code>) inside your cell's Content View. This will contain all of your cell's content. Position it and apply necessary constraints in the Storyboard.
2. Create another <code>UIView</code>. This one will be the one with the shadow (let's refer to it as <code>shadowLayer</code>). Position it exactly as you did <code>mainBackground</code>, but behind it, and apply the same constraints.
3. 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 <code>UIBezierPath</code> 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 <code>UIBezierPath</code> depends on <code>shadowLayer</code>'s bounds, but the bounds are not properly set by the time <code>cellForRowAtIndexPath</code> is called. So, you need to adjust the <code>shadowPath</code> based on <code>shadowLayer</code>'s bounds. The best way to do this is to subclass <code>UIView</code>, and add a property observer to the bounds property. Then set all the properties for the shadow in <code>didSet</code>. Remember to change the class of your <code>shadowLayer</code> 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
}
}
1. Create a <code>UIView</code> (let's refer to it as <code>mainBackground</code>) inside your cell's Content View. This will contain all of your cell's content. Position it and apply necessary constraints in the Storyboard.
2. Create another <code>UIView</code>. This one will be the one with the shadow (let's refer to it as <code>shadowLayer</code>). Position it exactly as you did <code>mainBackground</code>, but behind it, and apply the same constraints.
3. 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 <code>UIBezierPath</code> 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 <code>UIBezierPath</code> depends on <code>shadowLayer</code>'s bounds, but the bounds are not properly set by the time <code>cellForRowAtIndexPath</code> is called. So, you need to adjust the <code>shadowPath</code> based on <code>shadowLayer</code>'s bounds. The best way to do this is to subclass <code>UIView</code>, and add a property observer to the bounds property. Then set all the properties for the shadow in <code>didSet</code>. Remember to change the class of your <code>shadowLayer</code> 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
}
}