Swift on OS X: 如何访问当前 CGContext 以在 -[NSView drawRect:] 中绘图
Swift on OS X: How to access the current CGContext for drawing in -[NSView drawRect:]
设置:
Xcode6.1
OS X 10.9.5
Swift Mac 基于文档的应用程序目标
问题:
我正在使用 Swift 制作一个 Cocoa Mac 应用程序(不是iOS!)。我有一个自定义 NSView
子类。我想覆盖 -drawRect:
,并访问当前 CGContext
以使用 CoreGraphics APIs.
进行一些绘图
但是,我似乎无法访问 Swift 中的当前 CGContext
(我在 ObjC 中做过数百次)。这是我的代码:
import Cocoa
class Canvas: NSView {
override func drawRect(dirtyRect: CGRect) {
if let ctx: CGContext! = NSGraphicsContext.currentContext()?.CGContext {
// do drawing
}
}
}
当我 运行 时,我在 drawRect
实现的第一行立即崩溃:
-[NSWindowGraphicsContext CGContext]: unrecognized selector sent to instance 0x60800005e840
我做错了什么?如何获取当前 CGContext
以在 Swift 中绘图?
注意:
我绝对想使用 CoreGraphics API。除非在 Swift 中使用 CoreGraphics API 是完全不可能的,否则请不要回复有关如何使用 AppKit 绘图 API 的建议(我不在乎它们是否更容易)。我想知道如何在 OS X.
上使用 Swift 的 CoreGraphics
遗憾的是,CGContext
仅适用于 10.10+。还有 graphicsPort
,但它的类型为 UnsafeMutablePointer<Void>
(并且可能必须进行一些争论才能恢复可行的 CGContext
),并且在 10.10 中已弃用。
如果这看起来不可行,您可以使用 CGBitmapContextCreate
创建位图上下文并绘制到其中;然后你可以从中检索图像并绘制它以查看结果。
例子
Swift 3+
class CustomView: NSView {
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.current?.CGContext
} else if let contextPointer = NSGraphicsContext.currentContext()?.graphicsPort {
let context: CGContextRef = Unmanaged.fromOpaque(COpaquePointer(contextPointer)).takeUnretainedValue()
return context
}
return nil
}
}
private func saveGState(drawStuff: (ctx:CGContextRef) -> ()) -> () {
if let context = self.currentContext {
CGContextSaveGState (context)
drawStuff(ctx: context)
CGContextRestoreGState (context)
}
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
saveGState { ctx in
// Drawing code here.
}
}
}
Swift 2
class CustomView: NSView {
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.currentContext()?.CGContext
} else if let contextPointer = NSGraphicsContext.currentContext()?.graphicsPort {
let context: CGContextRef = Unmanaged.fromOpaque(COpaquePointer(contextPointer)).takeUnretainedValue()
return context
}
return nil
}
}
private func saveGState(drawStuff: (ctx:CGContextRef) -> ()) -> () {
if let context = self.currentContext {
CGContextSaveGState (context)
drawStuff(ctx: context)
CGContextRestoreGState (context)
}
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
saveGState { ctx in
// Drawing code here.
}
}
}
Eporediese的答案可以更新为
Swift 4
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.current?.cgContext
} else if let contextPointer = NSGraphicsContext.current?.graphicsPort {
return Unmanaged.fromOpaque(contextPointer).takeUnretainedValue()
}
return nil
}
}
设置:
Xcode6.1
OS X 10.9.5
Swift Mac 基于文档的应用程序目标
问题:
我正在使用 Swift 制作一个 Cocoa Mac 应用程序(不是iOS!)。我有一个自定义 NSView
子类。我想覆盖 -drawRect:
,并访问当前 CGContext
以使用 CoreGraphics APIs.
但是,我似乎无法访问 Swift 中的当前 CGContext
(我在 ObjC 中做过数百次)。这是我的代码:
import Cocoa
class Canvas: NSView {
override func drawRect(dirtyRect: CGRect) {
if let ctx: CGContext! = NSGraphicsContext.currentContext()?.CGContext {
// do drawing
}
}
}
当我 运行 时,我在 drawRect
实现的第一行立即崩溃:
-[NSWindowGraphicsContext CGContext]: unrecognized selector sent to instance 0x60800005e840
我做错了什么?如何获取当前 CGContext
以在 Swift 中绘图?
注意:
我绝对想使用 CoreGraphics API。除非在 Swift 中使用 CoreGraphics API 是完全不可能的,否则请不要回复有关如何使用 AppKit 绘图 API 的建议(我不在乎它们是否更容易)。我想知道如何在 OS X.
上使用 Swift 的 CoreGraphics遗憾的是,CGContext
仅适用于 10.10+。还有 graphicsPort
,但它的类型为 UnsafeMutablePointer<Void>
(并且可能必须进行一些争论才能恢复可行的 CGContext
),并且在 10.10 中已弃用。
如果这看起来不可行,您可以使用 CGBitmapContextCreate
创建位图上下文并绘制到其中;然后你可以从中检索图像并绘制它以查看结果。
例子
Swift 3+
class CustomView: NSView {
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.current?.CGContext
} else if let contextPointer = NSGraphicsContext.currentContext()?.graphicsPort {
let context: CGContextRef = Unmanaged.fromOpaque(COpaquePointer(contextPointer)).takeUnretainedValue()
return context
}
return nil
}
}
private func saveGState(drawStuff: (ctx:CGContextRef) -> ()) -> () {
if let context = self.currentContext {
CGContextSaveGState (context)
drawStuff(ctx: context)
CGContextRestoreGState (context)
}
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
saveGState { ctx in
// Drawing code here.
}
}
}
Swift 2
class CustomView: NSView {
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.currentContext()?.CGContext
} else if let contextPointer = NSGraphicsContext.currentContext()?.graphicsPort {
let context: CGContextRef = Unmanaged.fromOpaque(COpaquePointer(contextPointer)).takeUnretainedValue()
return context
}
return nil
}
}
private func saveGState(drawStuff: (ctx:CGContextRef) -> ()) -> () {
if let context = self.currentContext {
CGContextSaveGState (context)
drawStuff(ctx: context)
CGContextRestoreGState (context)
}
}
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
saveGState { ctx in
// Drawing code here.
}
}
}
Eporediese的答案可以更新为
Swift 4
private var currentContext : CGContext? {
get {
if #available(OSX 10.10, *) {
return NSGraphicsContext.current?.cgContext
} else if let contextPointer = NSGraphicsContext.current?.graphicsPort {
return Unmanaged.fromOpaque(contextPointer).takeUnretainedValue()
}
return nil
}
}