Blog

Swift Tip: Unwrapping Optionals

When we use the ! operator to force-unwrap an optional value in Swift Talk, we sometimes hear from viewers that it would be better not to use force-unwrapping. However, while we try to be very careful about force-unwrapping an optional value, it’s mostly a very deliberate choice if we do force-unwrap. The key questions we ask ourselves in these cases is: does the nil value occur due to a programmer error?

Consider the example of creating an URL from a static string like this:

let url: URL? = URL(string: "https://www.objc.io")

The URL initializer is failable, because not every string represents a valid URL:

let url: URL? = URL(string: "πŸ€”")
assert(url == nil)

However, if we create a URL from a static string, it’s the programmer’s responsibility to specify a valid URL. A string that results in a nil value is like a typo or a logic error in your code. Therefore we force-unwrap the result to crash immediately in case we’ve made a mistake:

let url: URL = URL(string: "https://www.objc.io")!

If you use force-unwrapping like this carefully, you can read the ! character in your code as an assertion. It signifies a check for the correctness of your code.

We encountered a similar, though less obvious example when writing a concurrent map function in Swift Talk 90:

extension Array {
    func concurrentMap<B>(_ transform: @escaping (Element) -> B) -> [B] {
        var result = Array<B?>(repeating: nil, count: count)
        let q = DispatchQueue(label: "sync queue")
        DispatchQueue.concurrentPerform(iterations: count) { idx in
            let element = self[idx]
            let transformed = transform(element)
            q.sync {
                result[idx] = transformed
            }
        }
        return result.map { $0! }
    }
}

At the very end of the function, we map over the result array and force unwrap all the values. We could have avoided the force-unwrap by using flatMap instead of map, but this would only serve to mask potential programming errors. The result array must contain the same number of elements as the original array, i.e. there must not be a nil value in it. If there is, we have made a mistake and should crash immediately.

We talk much more about handling optionals in Swift Talk 93: besides force-unwrapping, we look at API design with optionals, optional chaining, implicitly-unwrapped optionals and more.

Subscribe to access all our episodes.

Stay up-to-date with our newsletter or follow us on Twitter.

Back to the Blog

recent posts