NSView初始化时bounds属性失效的问题
NSView初始化时bounds属性失效的问题

NSView初始化时bounds属性失效的问题

问题描述

在NSView中,设置bounds时,发现bounds失效:

class ScreenshotOverlayView: NSView {
    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        layer?.backgroundColor = NSColor.black.withAlphaComponent(0.2)  // 设置半透明的黑色背景
        let mutablePath = CGMutablePath()
        mutablePath.addRect(bounds) // 设置全屏大小的矩形

        let shapeLayer = CAShapeLayer()
        shapeLayer.path = mutablePath    // shapeLayer的路径应该是 bounds 全屏,所以遮罩层是全部,应该半透明的黑色背景
        layer?.mask = selectionLayer
    }
}

NSView中的bounds表示视图当前大小的区域,而CGMutablePath.addRect()表示,将视图当前大小的矩形路径添加到mutablePath路径中。

经过查询了解到,在NSView的构造方法init()中,使用bounds时视图并没有真正布局完成,bounds值仍然是(0,0,0,0),所以mutablePath路径是空的。

在NSView的生命周期中,init(frame:)是非常早的阶段,bounds默认是(0,0,0,0),底层的CALayer还没完全初始化,视图还没有加入视图层次结构进行布局。

解决方案

把绘图逻辑延迟到视图真正有尺寸后再做。可以放到layout()或viewDidMoveToWindow()中:

1、重写layout:

自动布局时会调用此方法,可重写处理子视图布局。

override func layout() {
    layer?.backgroundColor = NSColor.black.withAlphaComponent(0.2)  // 设置半透明的黑色背景
    let mutablePath = CGMutablePath()
    mutablePath.addRect(bounds) // 设置全屏大小的矩形

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = mutablePath    // shapeLayer的路径应该是 bounds 全屏,所以遮罩层是全部,显示半透明的黑色背景
    layer?.mask = selectionLayer
}

2、重写viewDidMoveToWindow()

viewDidMoveToWindow方法,在视图添加到 window 时调用。

override func viewDidMoveToWindow() {
    layer?.backgroundColor = NSColor.black.withAlphaComponent(0.2)  // 设置半透明的黑色背景
    let mutablePath = CGMutablePath()
    mutablePath.addRect(bounds) // 设置全屏大小的矩形

    let shapeLayer = CAShapeLayer()
    shapeLayer.path = mutablePath    // shapeLayer的路径应该是 bounds 全屏,所以遮罩层是全部,显示半透明的黑色背景
    layer?.mask = selectionLayer
}

总结

问题的原因在于,NSView初始化时bounds可能是(0,0,0,0),因此应该考虑在layout或viewDidMoveToWindow生命周期方法中,使用bounds。

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注