Swift в OS X: как получить доступ к текущему CGContext для рисования -[NSView drawRect:]

настройка:

Xcode 6.1
OS X 10.9.5
Swift Mac цель приложения на основе документов

вопрос:

я использую Свифт чтобы сделать какао Mac app (не iOS!). У меня есть обычай NSView подкласс. Я хотел бы переопределить -drawRect:, и получить доступ к текущему CGContext для рисования с помощью CoreGraphics APIs.

тем не менее, я не могу получить доступ к ток CGContext в Swift (что-то, что я делал сотни раз в 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?

Примечание:

Я определенно хочу использовать API CoreGraphics. Если использование API CoreGraphics в Swift полностью невозможно, пожалуйста, не отвечайте предложения о том, как использовать API рисования AppKit вместо этого (мне все равно, если они проще). Я хочу знать, как использовать CoreGraphics от Swift на OS X.

2 ответов


к сожалению, CGContext доступно только в 10.10+. Есть также graphicsPort, но он имеет тип UnsafeMutablePointer<Void> (и, по-видимому, необходимо несколько поспорить, чтобы восстановить жизнеспособный CGContext), и он устарел в 10.10.

если это не кажется жизнеспособным, вы можете создать контекст растрового изображения с помощью CGBitmapContextCreate и нарисуйте это; затем вы можете получить изображение из него и нарисовать это, чтобы увидеть результаты.


пример

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