xcodemacoscocoaswiftcgcontext

Swift on OS X: How to access the current CGContext for drawing in -[NSView drawRect:]


Setup:

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

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.

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:

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:

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

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

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.


Solution

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

    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.