Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Implicitly Unwrapped Optionals?

Tags:

swift

I'm porting an NSView to Swift and I need to use Quartz CGContextAddPath.

import Cocoa

class MYView: NSView {

    init(frame: NSRect) {
        super.init(frame: frame)
    }

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)


        NSColor .redColor() .set()
        NSRectFill(self.bounds)
        var p :CGMutablePathRef = CGPathCreateMutable()
        var ctx =  NSGraphicsContext.currentContext().graphicsPort()
        CGContextAddPath(ctx, p) // compiler rejects this line

    }

}

How do you understand this error message ?

Cannot convert the expression's type 'Void' to type 'CGContext!'

The Swift signature of CGContextAddPath is:

func CGContextAddPath(context: CGContext!, path: CGPath!)

What is my error ?

When I use this:

let context = UnsafePointer<CGContext>(ctx).memory

I now have a runtime error:

Jun 3 15:57:13 xxx.x SwiftTest[57092] <Error>: CGContextAddPath: invalid context 0x7fff73bd0060. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

Here is the code that I'm currently using:

import Cocoa

class MYView: NSView {

    init(frame: NSRect) {
        super.init(frame: frame)
    }

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)

        var p :CGMutablePathRef =  CGPathCreateMutableCopy( CGPathCreateWithRoundedRect(self.bounds, 10, 10, nil))
        var ctx =  NSGraphicsContext.currentContext().graphicsPort()
        let context = UnsafePointer<CGContext>(ctx).memory

        CGContextAddPath(context, p) // compiler no longer rejects this line
        var blueColor = NSColor.blueColor()
        CGContextSetStrokeColorWithColor(context, NSColor.blueColor().CGColor)
        CGContextSetLineWidth(context, 2)
        CGContextStrokePath(context)

    }

}
like image 212
user3585425 Avatar asked Jun 03 '14 13:06

user3585425


People also ask

How do I use optionals in Swift?

You can simply represent a Data type as Optional by appending ! or ? to the Type . If an optional contains a value in it, it returns value as Optional<Value> , if not it returns nil .

What is implicit in Swift?

Implicitly unwrapping that optional means that it's still optional and might be nil, but Swift eliminates the need for unwrapping.

What will happen if you try to unwrap an optional that contains nil like so?

Unwrap an optional type with the nil coalescing operator If a nil value is found when an optional value is unwrapped, an additional default value is supplied which will be used instead. You can also write default values in terms of objects.

What is forced unwrapping in Swift?

Forced unwrapping is an action done on the normal Optionals. Implicitly unwrapped Optionals are Optionals, usually used for class initialization and will pass values without exclamation mark when used.


2 Answers

As of Swift 1.0

If your deployment target is 10.10 you can use the convenience method introduced with Yosemite.

let context = NSGraphicsContext.currentContext().CGContext

If you have to support 10.9 you'll have to cast the context manually as per below.

let contextPtr = NSGraphicsContext.currentContext().graphicsPort
let context = unsafeBitCast(contextPtr, CGContext.self)
like image 164
user3585425 Avatar answered Oct 02 '22 07:10

user3585425


Use NSGraphicsContext.currentContext().graphicsPort(). It returns void*. You have to cast it to CGContextRef

let ctx = UnsafePointer<CGContext>(NSGraphicsContext.currentContext().‌​graphicsPort()).memo‌​ry
like image 31
fnc12 Avatar answered Oct 01 '22 07:10

fnc12