Swift 如何在自定义CALayer子类的重写draw函数中在macOS上绘制字符串?

Swift 如何在自定义CALayer子类的重写draw函数中在macOS上绘制字符串?,swift,string,macos,calayer,cgcontext,Swift,String,Macos,Calayer,Cgcontext,为什么下面的代码没有在macOS应用程序中绘制字符串 class MyLayer: CALayer { override func draw(in ctx: CGContext) { let font = NSFont.systemFont(ofSize: 18) let text = "TEXT" let textRect = CGRect(x: 100, y: 100, width: 100, height: 100)

为什么下面的代码没有在macOS应用程序中绘制字符串

class MyLayer: CALayer {
    override func draw(in ctx: CGContext) {
        let font = NSFont.systemFont(ofSize: 18)
        let text = "TEXT"
        let textRect = CGRect(x: 100, y: 100, width: 100, height: 100)
        text.draw(in: textRect, withAttributes: [.font: font])
    }
}

CALayer
draw(in:)
方法构建在核心图形之上。所有核心图形绘制函数都将
CGContext
作为参数(或者,在Swift中,是
CGContext
上的方法)。这就是核心动画将
CGContext
传递给
draw(in:)
方法的原因

但是,
String
上的
draw(in:withAttributes:)
方法不是核心图形的一部分。它是AppKit的一部分。AppKit的绘图方法不直接在
CGContext
上运行。它们在
NSGraphicsContext
上运行(它封装了
CGContext
)。但是,从
draw(in:withAttributes:)
方法中可以看到,AppKit的绘图函数不接受
NSGraphicsContext
参数,也不是
NSGraphicsContext
上的方法

相反,有一个全局(每个线程)
NSGraphicsContext
。AppKit绘图方法使用此全局上下文。由于您在核心动画级别编写代码,AppKit没有为您设置全局
NSGraphicsContext
。您需要自己进行设置:

class MyLayer: CALayer {
    override func draw(in ctx: CGContext) {
        let nsgc = NSGraphicsContext(cgContext: ctx, flipped: false)
        NSGraphicsContext.current = nsgc

        let font = NSFont.systemFont(ofSize: 18)
        let text = "TEXT"
        let textRect = CGRect(x: 100, y: 100, width: 100, height: 100)
        text.draw(in: textRect, withAttributes: [.font: font])
    }
}

这是一个多么清晰、内容丰富的回答啊!出于好奇:
CGContext
本身不是有字符串绘制方法吗?核心图形的字符串绘制功能在几年前就被弃用了。文档告诉您改为使用核心文本。如果您只需要非常简单的字符串绘制,那么使用AppKit的方法可能就足够了。如果您需要更大的功率,请查看文本工具包。