I have a custom UIPresentationController
in which I overrode the presentedView
as follows:
override var presentedView: UIView? {
guard let view = super.presentedView else { return nil }
let shadowLayer = CALayer()
shadowLayer.shadowPath = .init(rect: view.bounds, transform: .none)
shadowLayer.shadowRadius = 6
shadowLayer.shadowColor = .init(gray: 0, alpha: 0.15)
shadowLayer.backgroundColor = view.layer.backgroundColor
shadowLayer.shadowOpacity = 1
shadowLayer.shadowOffset = .init(width: 0, height: -10)
shadowLayer.shouldRasterize = true
shadowLayer.rasterizationScale = UIApplication.screen?.scale ?? 1.0
view.layer.insertSublayer(shadowLayer, at: 0)
shadowLayer.position = view.layer.position
shadowLayer.bounds = view.bounds
view.layer.masksToBounds = false
return view
}
Then for efficiency I thought why creating a new CALayer
every time presetedView
is calculated and decided to hold the the layer as a property of the class and only update the shadowPath
. After that the layer is no longer visible and not in the view hierarchy anymore. I also tried to insert sublayer only once by checking if layer is present in the sublayers but it didn't help
Does anyone know what am I missing?
UPDATE: Declared a property
private let shadowLayer = {
let shadowLayer = CALayer()
shadowLayer.shadowRadius = 6
shadowLayer.shadowOpacity = 1
shadowLayer.shadowOffset = .init(width: 0, height: -10)
shadowLayer.shouldRasterize = true
shadowLayer.rasterizationScale = UIApplication.screen?.scale ?? 1.0
shadowLayer.masksToBounds = false
return shadowLayer
}()
And deleted initialization code from here. After that the layer dissappears
override var presentedView: UIView? {
guard let view = super.presentedView else { return nil }
shadowLayer.shadowPath = .init(rect: view.bounds, transform: .none)
shadowLayer.shadowColor = .init(gray: 0, alpha: 0.15)
shadowLayer.backgroundColor = view.layer.backgroundColor
view.layer.insertSublayer(shadowLayer, at: 0)
shadowLayer.position = view.layer.position
shadowLayer.bounds = view.bounds
view.layer.masksToBounds = false
return view
}
Turns out I was calculating layers position
& shadowPath
wrong! Because sublayers coordinating system is relative to superlayers system we should draw path inside views bounds
not frame
and calculate center point of the frame manually
override var presentedView: UIView? {
guard let view = super.presentedView else { return nil }
shadowLayer.shadowPath = .init(rect: view.bounds, transform: .none)
shadowLayer.position = .init(x: view.bounds.midX, y: view.bounds.midY)
shadowLayer.bounds = view.bounds
shadowLayer.backgroundColor = view.layer.backgroundColor
if shadowLayer.superlayer == nil {
view.layer.insertSublayer(shadowLayer, below: nil)
}
view.layer.masksToBounds = false
return view
}