Swift: Avoiding double-wrapped optionals with conditional downcasting

27th February, 2015 — Aral Balkan

Yesterday, I took the plunge and updated Heartbeat to Xcode 6.3 Beta 2. It was actually not a painful process with the automatic migration tool shouldering the brunt of the work for me.

One thing I did notice in my code, however, was a double-wrapped optional where I was trying to access the layer of the content view of a window.

In my original code, I had:

Swift:  if let layer = self.window?.contentView.layer? { //…

While that works in the release build, Swift 1.2 in Xcode 6.3 Beta 2 was having none of it.

My initial, naïve refactoring gave me this:

Swift: if let window = self.window, doubleWrappedOptionalWTF = window.contentView.layer, layer = doubleWrappedOptionalWTF { //…

So, to understand why I was getting a double-wrapped optional (CALayer??), I wrote out the code in longhand:

Swift: let window:NSWindow? = self.window
if let window = window
{
    let contentView:NSView? = window.contentView as? NSView
    if let contentView = contentView
    {
        let layer:CALayer? = contentView.layer
        if let layer = layer
        {
            // Do something with the layer…
        }
    }
}

Ah, well now it’s clear: the “double-wrapping” is because I wasn’t casting contentView, which returns AnyObject.

So, let’s apply that back to the one-liner:

Swift: if let window = self.window, contentView = window.contentView as? NSView, layer = contentView.layer { //…

Much nicer.

But I can’t really call it beautiful.