The Implicitly Unwrapped Optional & When To Use It



Since the advent of Swift, our behavior towards nil values have greatly changed. Swift brings type safety, and also works hard to prevent sending messages to nil by introducing Optionals. Optionals force you to write guards around your optional code at compile time using "optional binding" which, while making your code more secure, also makes it look a bit messy. Implicitly unwrapped optionals behave like optionals: they can be set to nil, you can use optional chaining on implicitly unwrapped optional variables, and can check them for nil equality. The only difference between them is that implicitly unwrapped optionals are a promise to the swift compiler that it's value will NOT be nil when accessed at runtime.

The Implicitly Unwrapped Optional

The first thing to remember about the implicitly unwrapped optional is that while you can use them in all the same places that you can use optionals, it isn't an optional and it isn't a class. This seems a little weird, but the implicitly unwrapped optional is actually an enum represented by the name ImplicitlyUnwrappedOptional while the optional is an enum represented by the name Optional. A quick look at the Swift library more or less shows this as the declaration for ImplicitlyUnwrappedOptional:

public enum ImplicitlyUnwrappedOptional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)

    /// Construct a non-\ `nil` instance that stores `some`.
    public init(_ some: Wrapped)

    /// Construct an instance from an explicitly unwrapped optional
    /// (`T?`).
    public init(nilLiteral: ())

}

One more look at the Swift Library proves my point that ImplicitlyUnwrappedOptionals are not Optionals because the Optional enum has a separate declaration and there is no sign of inheritance that states that either one inherits from the other:

public enum Optional<Wrapped> : ExpressibleByNilLiteral {
    case none
    case some(Wrapped)

    /// Construct a non-\ `nil` instance that stores `some`.
    init(_ some: Wrapped)

}

This is despite a seemingly contradictory quote from Apple's Swift Programming Book:

An implicitly unwrapped optional is a normal optional behind the scenes, but can also be used like a non optional value

Do you see what I mean? They're different but also the same. Maybe, this is alluding to the "compiler magic" I mention a bit later. I personally think it just means that they are implemented the same way. To be honest, we won't know which one it is until Swift comes out as open source this fall. Hooray, open source!

Further inspection of the ImplicitlyUnwrappedOptional enum actually shows us a neat little comment that explains why the implicitly unwrapped optional enum compared to all other enums is different and more special:

An optional type that allows implicit member access (via compiler magic). The compiler has special knowledge of the existence of ImplicitlyUnwrappedOptional

Due to this compiler magic, we are able to wrap our property declarations in this enum using the postfix > !> as syntactic sugar like so:

class BermudaTriangle { 
    let theEverPresentKraken: Kraken! 
    init() { 
        theEverPresentKraken = Kraken() 
    } 
}

As opposed to how it actually looks without the !:

class BermudaTriangle { 
    let theEverPresentKraken: ImplicitlyUnwrappedOptional<Kraken> = .None 
    init() { 
        theEverPresentKraken = ImplicitlyUnwrappedOptional.Some(Kraken()) 
    } 
}

As you can see, in this scenario, the implicitly unwrapped optional is an enum of type ImplicitlyUnwrappedOptional that wraps an instance of the Kraken class in it's .Some case value.

At it's introduction the implicitly unwrapped optional raised a bit of concern amongst developers because of the nature of Swift and how it handles messages to nil. If a message is sent to nil in Swift, the application crashes. Swift does a great job of catching cases where this happens at compile time and will throw an error to let you know to guard against these scenarios. However, the implicitly unwrapped optional actually provides a bypass around these errors. It's because of this bypass implementation that concerns began to rise around the use of the implicitly unwrapped optional.

iss0p.jpg

Apple actually expressly states this about the Implicitly Unwrapped Optional:

Because the value of an implicitly unwrapped optional is automatically unwrapped when you use it, there’s no need to use the ! operator to unwrap it. That said, if you try to use an implicitly unwrapped optional that has a value of nil, you’ll get a runtime error.
 

When to Use it

You should only ever mark a variable as an Implicitly Unwrapped Optional if you can guarantee that it will NOT be nil at the time it's called. I can't express this enough. If you have a question about the existence of an implicitly unwrapped optional variable at runtime, then it should NOT have been an implicitly unwrapped optional to begin with. Remember this: implicitly unwrapped optionals promise to have a value when accessed at runtime, but also have the ability to be mutated to nil at runtime as well. Here's an example:

var string: String! = "I'm a string!" 
string.capitalizedString //NO crash at this point. It will return "I'm A String". 

string = nil //Can be mutated to nil at runtime string.capitalizedString //CRASH - Can't send messages to nil in Swift!

Now that we got that out of the way, here are scenarios where it's totally appropriate to create an implicitly unwrapped optional:

(Author's Note: A general rule you should use from here on out is that if you can't find your scenario in this list, then you should be using an optional instead. Feel free to make suggestions of scenarios to add to this in the comments below. If they are valid, then good for you! I will immediately update this post with it. 😄)

 

When Referencing an Object from Interface Builder

When writing an iOS app, we have the luxury of using wonderful tools from Interface Builder like Storyboards. The problem we have when using Interface Builder is connecting our visual elements to our code through IBOutlets. Since it's entirely possible (and common!) for someone to have over 10 IBOutlets in their classes, it becomes a bit unwieldy to use IBOutlet properties as straight optionals. Your code could be littered with if lets if you don't use implicitly unwrapped optionals. In fact, when dragging an outlet from a storyboard to a swift file, Xcode generates these properties as implicitly unwrapped optionals for you!

When we use storyboards, we can make a few assumptions. The first assumption is that we can rely on Interface Builder to create our references correctly at runtime. The second assumption is this; since storyboard elements are user facing, we always test our outlet code in the simulator by visually verifying that the element you created is there. Take this example:

class BusinessCardView: UIView { 
    @IBOutlet private weak var jobTitleLabel: UILabel! 

    override func layoutSubviews() { 
        super.layoutSubviews() 
        jobTitleLabel.text = "The Boss Man" 
    } 
}

Here, a normal developer would make sure that their label on the BusinessCardView is displaying "The Boss Man". How do we test this? Well we run the code, of course! If you forgot to connect the jobTitleLabel then when iOS loads this code at runtime, jobTitleLabel will be nil but you will get this VERY clear exception:

In this case, your dev cycle would consist of you making sure the outlet is connected properly and connecting it if it wasn't.

A great place to use implicitly unwrapped optionals are also when loading prototype entities from Interface Builder. If you have a prototype cell that you created in a storyboard and you loaded it using dequeueReusableCellWithIdentifier, then an implicitly unwrapped optional would be great. This has the added benefit of not having a list of optional binding in scenarios where you have multiple cell prototypes for one UITableView. This is because of the same reason as stated above: you won't actually release an app with new visual elements without testing them first.

Unless you don't actually test your code. Then God rest your soul.

 

When Interacting with an External Framework You Have No Control Of

This one is fairly obvious. Since you can't change the source code of an external framework such as UIKit, any implicitly unwrapped optionals there can't be helped. Take the example of creating a UITableViewRowAction:

let rowAction = UITableViewRowAction(style: .Normal, title: "") { (rowAction: UITableViewRowAction!, indexPath: NSIndexPath!) -> Void in 
    //do some shtuff. We can't help that rowAction and indexPath are implicitly unwrapped. We're gonna have to trust that Apple knows their stuff. 
}
 

When You Have a Property that Can't Be Populated During Initialization

Apple explains this very well in their Swift book:

Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization.

If you want further details on this straight from the source, you can find it at the Unowned References and Implicitly Unwrapped Optional Properties section in their documentation.

Many view based classes (including UIViewControllers) have their initialization split up into phases. First is the initialization phase where the pointer to the class instance is created (This is where you assign your default values to your properties and is generally in the classes init function). Next is when the actual representation of the view is loaded and attached to the view hierarchy. You see this with UIViews and UIViewControllers where these two phases are tightly coupled and call one after the other. So in scenarios where you need to populate a variable with a view's property values directly after initialization, it is ok to use implicitly unwrapped optionals. Take this example of a UIView subclass created in Interface Builder:

class KrakenView: UIView { 
    var startingOrigin: CGPoint! 
    override func awakeFromNib() { 
        super.awakeFromNib() 
        startingOrigin = frame.origin 
    } 
}

In this example, we need to hold on to the view's starting point for whatever reason. The problem is, we can't set the origin in the init function because the view won't have an origin until it's loaded in it's second initialization phase - awakeFromNib().

 

Conclusion

There are VERY few scenarios where it is ok to use implicitly unwrapped optionals. The nature of Swift is to encourage the developer to be as safe as possible, so it’s highly recommended that we default to using Swift’s Optional Type as much as possible in order to prevent crashes from sending messages to nil. So here’s to writing safer code!

Happy coding fellow nerds!