Swift on OS X:如何访问当前的CGContext进行绘图-[NSView drawRect:]

时间:2023-01-24 08:45:23

Setup:

Xcode 6.1
OS X 10.9.5
Swift Mac Document-based Application target

Xcode 6.1 OS X 10.9.5 Swift Mac基于文档的应用程序目标

Question:

I am using Swift to make a Cocoa Mac app (NOT iOS!). I have a custom NSView subclass. I'd like to override -drawRect:, and access the current CGContext to do some drawing using the CoreGraphics APIs.

我正在使用Swift制作一个Cocoa Mac应用(不是iOS!)我有一个定制的NSView子类。我想重写-drawRect:,并访问当前的CGContext,使用CoreGraphics api进行一些绘图。

However, I can't seem to access the current CGContext in Swift (something I've done hundreds of times in ObjC). Here's my code:

然而,我似乎无法用Swift访问当前的CGContext(我在ObjC中已经做了数百次)。这是我的代码:

import Cocoa

class Canvas: NSView {
    override func drawRect(dirtyRect: CGRect) {
        if let ctx: CGContext! = NSGraphicsContext.currentContext()?.CGContext {
            // do drawing
        }
    }
}

When I run, I get an immediate crash on the first line of my drawRect implementation:

当我运行时,我的drawRect实现的第一行会立即崩溃:

-[NSWindowGraphicsContext CGContext]: unrecognized selector sent to instance 0x60800005e840

What am I doing wrong? How do I fetch the current CGContext for drawing in Swift?

我做错了什么?如何以Swift的方式获取当前的CGContext ?

NOTE:

I definitely want to use the CoreGraphics API. Unless using the CoreGraphics API in Swift is entirely impossible, please do not respond with suggestions on how to use AppKit drawing APIs instead (I don't care if they are easier). I want to know how to use CoreGraphics from Swift on OS X.

我肯定想使用CoreGraphics API。除非在Swift中使用CoreGraphics API是完全不可能的,否则请不要回复关于如何使用AppKit绘图API的建议。我想知道如何在OS X上使用Swift的CoreGraphics。

2 个解决方案

#1


8  

Unfortunately, CGContext is only available in 10.10+. There’s also graphicsPort, but it has type UnsafeMutablePointer<Void> (and presumably must be wrangled somewhat to recover a viable CGContext), and it’s deprecated in 10.10.

不幸的是,CGContext只在10.10+中可用。也有graphicsPort,但是它有UnsafeMutablePointer类型 (可能必须为恢复一个可行的CGContext而争论一番),它在10.10中被废弃了。

If that doesn’t seem viable, you could create a bitmap context using CGBitmapContextCreate and draw into that; then you can retrieve an image from it and draw that to see the results.

如果这看起来不可行,您可以使用CGBitmapContextCreate创建一个位图上下文,并从中提取;然后,您可以从中检索一个图像并将其绘制出来以查看结果。

#2


21  

Example

例子

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.
        }
    }
}

#1


8  

Unfortunately, CGContext is only available in 10.10+. There’s also graphicsPort, but it has type UnsafeMutablePointer<Void> (and presumably must be wrangled somewhat to recover a viable CGContext), and it’s deprecated in 10.10.

不幸的是,CGContext只在10.10+中可用。也有graphicsPort,但是它有UnsafeMutablePointer类型 (可能必须为恢复一个可行的CGContext而争论一番),它在10.10中被废弃了。

If that doesn’t seem viable, you could create a bitmap context using CGBitmapContextCreate and draw into that; then you can retrieve an image from it and draw that to see the results.

如果这看起来不可行,您可以使用CGBitmapContextCreate创建一个位图上下文,并从中提取;然后,您可以从中检索一个图像并将其绘制出来以查看结果。

#2


21  

Example

例子

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.
        }
    }
}