xcode OS X 上的 Swift:如何访问当前的 CGContext 以在 -[NSView drawRect:] 中进行绘图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29156765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:50:58  来源:igfitidea点击:

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

xcodemacoscocoaswiftcgcontext

提问by Todd Ditchendorf

Setup:

设置:

Xcode 6.1
OS X 10.9.5
Swift MacDocument-based Application target

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

Question:

题:

I am using Swiftto make a Cocoa Macapp (NOT iOS!). I have a custom NSViewsubclass. I'd like to override -drawRect:, and access the current CGContextto 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 CGContextin Swift (something I've done hundreds of times in ObjC). Here's my code:

但是,我似乎无法访问CGContextSwift 中的当前内容(我在 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 drawRectimplementation:

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

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

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

我究竟做错了什么?如何CGContext在 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.

我绝对想使用 CoreGraphics API。除非在 Swift 中使用 CoreGraphics API 是完全不可能的,否则请不要回复有关如何使用 AppKit 绘图 API 的建议(我不在乎它们是否更容易)。我想知道如何在 OS X 上使用 Swift 的 CoreGraphics。

采纳答案by Rob Rix

Unfortunately, CGContextis 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<Void>(并且可能必须进行一些争论才能恢复可行的CGContext),并且在 10.10 中已弃用。

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

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

回答by Eporediese

Example

例子

Swift 3+

斯威夫特 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

斯威夫特 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.
        }
    }
}

回答by freytag

Eporedieses answer can be updated to

Eporediese的回答可以更新为

Swift 4

斯威夫特 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
    }
}