8

I have the following code in swift which doesn't compile:

class CustomView: NSView {
  override func drawRect(dirtyRect: NSRect) {
    var contextPointer: COpaquePointer = NSGraphicsContext.currentContext()!.graphicsPort()
    var context: CGContext? = contextPointer as? CGContext
    CGContextSetRGBFillColor(context, 1, 0, 0, 1)
    CGContextFillRect(context, CGRectMake(0, 0, 100, 100))
    CGContextFlush(context)
  }
}

How do I convert COpaquePointer to CGContext?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Alfa07
  • 3,314
  • 3
  • 26
  • 39

5 Answers5

10

As of Developer Preview 5, NSGraphicsContext now has a CGContext property. It's not documented yet but it's in the header file:

@property (readonly) CGContextRef CGContext NS_RETURNS_INNER_POINTER NS_AVAILABLE_MAC(10_10);
robotspacer
  • 2,732
  • 2
  • 28
  • 50
7

This is kind of ugly; it would be better if the graphicsPort() method was updated to return a CGContextRef directly (like UIGraphicsGetCurrentContext()), rather than a void*. I added this extension to NSGraphicsContext to sweep it under the rug for now:

extension NSGraphicsContext {
  var cgcontext: CGContext {
    return Unmanaged<CGContext>.fromOpaque(self.graphicsPort()).takeUnretainedValue()
  }
}

Just call NSGraphicsContext.currentContext().cgcontext anywhere you need a CGContext.

jatoben
  • 3,079
  • 15
  • 12
3

This seems to be compiling:

var contextPointer = NSGraphicsContext.currentContext()!.graphicsPort()
let context = UnsafePointer<CGContext>(contextPointer).memory
Alfa07
  • 3,314
  • 3
  • 26
  • 39
  • Thanks! Not sure you need to use .currentContext()! though - isn't the type of currentContext already unwrapped? `class func currentContext() -> NSGraphicsContext!` – alaroldai Jun 03 '14 at 09:18
  • @alaroldai Yes, but I need CGContext not NSGraphicsContext – Alfa07 Jun 03 '14 at 18:21
  • See http://stackoverflow.com/questions/24016668/how-to-use-implicitly-unwrapped-optionals/24056236#24056236 – klotz Sep 24 '14 at 15:18
1

You are almost near. Try this code

class CustomView: NSView {
    override func drawRect(dirtyRect: NSRect) {

        var contextPointer = NSGraphicsContext.currentContext()!.graphicsPort()
        var context = UnsafePointer<CGContext>(contextPointer).memory

        CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0)
        CGContextFillRect(context, CGRectMake(0, 0, 100, 100))
        CGContextFlush(context)
    }
}
Yatheesha
  • 10,412
  • 5
  • 42
  • 45
0

In Xcode 6.3 / Swift 1.2, NSGraphicsContext.currentContext()!.graphicsPort returns UnsafeMutablePointer<Void> and you can cast it into CGContextRef using unsafeBitCast because it's just a C pointer. This just reinterpret the pointer value, so should work exactly same with C forced point cast.

    let p1  =   NSGraphicsContext.currentContext()!.graphicsPort
    let ctx =   unsafeBitCast(p1, CGContextRef.self)

Please take care that such reinterpreting-cast is always very dangerous and used only when you're sure on what you're doing.

eonil
  • 83,476
  • 81
  • 317
  • 516