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