CALayer 在属性中存储时消失

CALayer disappears when storing in a property

提问人:PigeonPO 提问时间:10/14/2023 最后编辑:PigeonPO 更新时间:10/16/2023 访问量:53

问:

我有一个习惯,我覆盖了以下内容:UIPresentationControllerpresentedView

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
    }

然后,为了提高效率,我想到为什么每次都要计算创建一个新的,并决定将该层作为类的属性,并且只更新 .之后,该图层不再可见,也不再位于视图层次结构中。我还尝试通过检查子图层中是否存在图层来仅插入一次子图层,但这没有帮助CALayerpresetedViewshadowPath

有谁知道我错过了什么?

更新: 声明的属性

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
    }()

并从这里删除了初始化代码。之后,该层消失

    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
    }
iOS Swift Core-动画 Calayer

评论

1赞 Duncan C 10/15/2023
我猜你在实施更改时犯了一个错误。我们无法确定为什么您的新代码在没有看到它的情况下无法正常工作。您能否编辑您的问题,在末尾添加一个部分,展示您的新代码,并告诉我们有关它如何出错的更多详细信息。
0赞 HangarRash 10/16/2023
每次调用都是重用相同的层实例。一个图层一次只能有一个。presentedViewsuperlayer

答:

0赞 Duncan C 10/15/2023 #1

您可以简单地添加代码以将 your 定义为实例变量并同时对其进行初始化:shadowLayer

var shadowLayer = CALayer()

(您也可以将其设置为惰性属性。

对上面的代码进行更改,然后只引用代码中的现有代码,而不是在函数中定义它(并初始化它)。shadowLayer

评论

0赞 PigeonPO 10/15/2023
这正是问题所在,在定义为实例属性后,它不再可见。真的很奇怪shadowLayer
0赞 Duncan C 10/16/2023
因此,请发布您的完整代码。我们无法调试您未共享的更改。
0赞 PigeonPO 10/16/2023 #2

原来我在计算层数,错了!因为子层坐标系是相对于超层系统的,所以我们应该在视图内绘制路径,而不是手动计算框架的中心点positionshadowPathboundsframe

    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
    }