Swift 5.2: No More Unsafe Pointer References

When people upgraded to Xcode 11.4, a lot of complaints started to appear on StackOverflow that code of the following form was giving trouble (this is an odd way to write this, but just bear with me):

let color = // some UIColor
var r = 0 as CGFloat
var g = 0 as CGFloat
var b = 0 as CGFloat
var a = 0 as CGFloat
color.getRed(&r, green: &g, blue: &b, alpha: &a)
let colorSpace = CGColorSpaceCreateDeviceRGB()
let array = [r, g, b, a]
let unsafePointer = UnsafePointer(array) // warning!
let cgc = CGColor(colorSpace: colorSpace, components: unsafePointer)
print(cgc)

The surprise that people complained about is that the line let unsafePointer = UnsafePointer(array) elicits a compiler warning. But this warning is perfectly correct. It was always dangerous to pass or assign an unsafe pointer directly, because the pointer is (get this) unsafe! It runs an immediate danger of pointing to deallocated memory; even if the memory is not in fact deallocated in your usage, it’s an incorrect thing to do.

The warning was introduced as part of Swift 5.2, and will be an error in a future version of Swift.
This change is really great, because a lot of people were in fact making this mistake. They are busted, and have a chance to correct their behavior before it’s too late. That sort of assignment should never have been allowed by the language, and the Swift folks have realized this and are on track to close the door on it. There are actually a lot of other ways to make this sort of mistake, visibly or behind the scenes, and they will all be handled by this new warning.

And what should you do if you actually encounter this warning? Well, I can’t cover every case, obviously, but here’s a way to write the last part of the example code safely:

let array = [r, g, b, a]
array.withUnsafeBufferPointer { ptr in
    if let adr = ptr.baseAddress {
        let cgc = CGColor(colorSpace: colorSpace, components: adr)
        print(cgc)
    }
}

The unsafe pointer is guaranteed to remain valid within the scope of the trailing closure body, so all is well.

(The WWDC 2020 videos include some excellent discussion of unsafe pointers generally, here and here.)

You Might Also Like…

Swift 5.5: Replacing GCD With Async/Await

Multithreading! The mere word sends shivers up one’s spine. And if it doesn’t, it should. Main thread and background threads. Code that runs asynchronously. Code that can run simultaneously with other code. Code that can run simultaneously with itself. Code that can share data across threads — possibly with disastrous consequences. Concurrency. Multithreaded code is …

Swift 5.5: Replacing GCD With Async/Await Read More »

    Sign Up

    Get more articles and exclusive content that takes your iOS skills to the next level.