Search code examples
macosswiftikimageview

Get a CGImageRef from an IKImageView in Swift


I'm trying to get the image associated with a view but Xcode returns me an error. Here is the code:

@IBOutlet var imageView: IKImageView // Link to the image view.

func saveImage() {
    var newImage: CGImageRef = imageView.image() // Line with an error.
}

I have a awakeFromNibfunction to set the image in the view. The code above returns me 'Unmanaged<CGImage>' is not convertible to 'CGImageRef'.

I know that types are optional in Swift but I don't understand why I get this error, the IKImageView Class Reference clearly said that get IKImageView's image return a CGImageRef.


Solution

  • This has to do with the bridging of Objective C APIs into Swift. The Swift versions of an API have been bridged (mostly automatically, I believe) by converting the original Objective C headers into a Swift version. In many cases, the conversion can work out what kind of value you're going to get back, and therefore in Swift you get a "normal" type that you can use as you'd expect.

    However, the conversion is still a work in progress. In this case, what you're seeing is a type used to help you manage memory manually when the conversion process doesn't know whether you're going to get back an object that's been retained for you or not, because the API doesn't have the conventional annotation that it could use to figure it out.

    The Unmanaged type effectively says "you have to tell me what to do with the contained value to get the memory management right". As soon as you get an Unmanaged value, you should call either one of its two methods:

    takeUnretainedValue() 
    takeRetainedValue()
    

    ...depending on whether the object you get back was a "+0" or "+1". So, you're expected to do something like:

    var newImage: CGImage = imageView.image().takeUnretainedValue()
    

    And as soon as you've done that (which you should do pretty much immediately), you've given Swift enough of a hint that it can now appropriately manage the object correctly with ARC, and got yourself a valid reference of the right type.

    This is touched on briefly at the end of the "Swift Interoperability in Depth" WWDC video from this year.