In Swift, how do I avoid both optionals and nil object references? In Swift, how do I avoid both optionals and nil object references? ios ios

In Swift, how do I avoid both optionals and nil object references?


You’re right, optionals can be a pain, which is why you shouldn't overuse them. But they're more than just something you have to deal with when using frameworks. They're a solution to an incredibly common problem: how to handle a call that returns a result that might be OK, or might not.

For example, take the Array.first member. This is a handy utility that gives you the first element of an array. Why is it useful to be able to call a.first, when you could just call a[0]? Because at runtime the array might be empty, in which case a[0] will explode. Of course you can check a.count beforehand – but then again

a. you might forget,

and

b. that results in quite ugly code.

Array.first deals with this by returning an optional. So you are forced to unwrap the optional before you can use the value that is the first element of the array.

Now, to your issue about the unwrapped value only existing inside the block with if let. Imagine the parallel code, checking the array count. It would be the same, right?

if a.count > 0 {    // use a[0]}// outside the block, no guarantee// a[0] is validif let firstElement = a.first {    // use firstElement}// outside the block, you _can't_// use firstElement

Sure, you could do something like perform an early return from the function if the count is zero. This works but is a bit error-prone – what if you forgot to do it, or put it in a conditional statement that didn't happen to run? Essentially you can do the same with array.first: check the count early in the function, and then later on do array.first!. But that ! is like a signal to you – beware, you are doing something dangerous and you will be sorry if your code isn't completely correct.

Optionals also help make the alternatives slightly prettier. Suppose you wanted to default the value if the array was empty. Instead of this:

array.count > 0 ? a[0] : somedefault

you can write this:

array.first ?? somedefault

This is nicer in several ways. It puts the important thing up front: the value you want is how the expression starts, followed by the default. Unlike the ternary expression, which hits you first with the checking expression, followed by the value you actually want, then finally the default. It's also more foolproof – much easier to avoid making a typo, and impossible for that typo to result in a runtime explosion.

Take another example: the find function. This checks if a value is in a collection and returns the index of its position. But the value may not be present in the collection. Other languages might handle this by returning the end index (which doesn't point to a value but rather one past the last value). This is what's termed a "sentinel" value – a value that looks like a regular result, but actually has special meaning. Like the previous example, you’d have to check the result was not equal to the end index before using it. But you have to know to do this. You have to look up the docs for find and confirm that's how it works.

With find returning an optional it's just natural, when you understand the optional idiom, to realize that the reason it does is because the result might not be valid for the obvious reason. And all the same things about safety mentioned above also apply – you can’t accidentally forget, and use the result as an index, because you have to unwrap it first.

That said, you can over-use optionals as they are a burden to have to check. This is why array subscripts don't return optionals – it would create so much hassle to have to constantly check and unwrap them, especially when you know for a fact that the index you're using is valid (for example, you're in a for loop over a valid index range of the array) that people would be using ! constantly, and thus clutter their code without benefit. But then the helper methods like first and last are added to cover common cases where people do want to quickly do an operation without having to check the array size first, but want to do it safely.

(Swift Dictionaries, on the other hand, are expected to be regularly accessed via invalid subscripts, which is why their [key] method does return an optional)

Even better is if the possibility of failure can be avoided altogether. For example, when filter matches no elements, it doesn’t return a nil optional. It returns an empty array. “Well obviously it would”, you might say. But you’d be surprised how often you see someone making a return value like an array optional when actually they just ought to return an empty one. So you’re completely correct in saying you should avoid optionals except when they’re necessary – it’s just a question of what necessary means. In the examples above I’d say they’re necessary, and a better solution to the alternatives.


Or am I supposed to just use optionals, and if that's what I'm doing, how is it any better than simply having null assignments to object references like other languages have?

If your computation may need to return an “special” value, then yes, in Swift you are supposed to use optionals. They are better than nullable types because they are explicit. It’s easy to miss a case where a pointer might be nil, it’s much harder (but entirely possible) to screw up with optionals.

If you use “if let” to safely unwrap them, you avoid crashes, but you are stuck inside the scope of the “if let” statement to work with the value, and you still have to handle the potential nil case.

That’s a feature. I mean, that’s the whole point of an optional type: you have to handle both cases (nil and non-nil) and you have to be explicit about it.

See Haskell’s Maybe type and monad for an example of a similar concept. The Maybe type is the exact equivalent of optional types, the Maybe monad makes it very easy to “chain” operations with these optional values without having to manually check for empty values all the time.


Swift 2 and later also includes guard let which solves many of the problems mentioned in this question. You can even re-use the variable name if you want:

func compute(value: Double?) -> Double? {    guard let value = value  else { return nil }    // ... `value` is now a regular Double within this function}

You can also use optional chaining (?) to short-circuit an expression when the first part returns nil:

let answer = compute(value: 5.5)?.rounded()

And nil coalescing (??) to provide a default value instead of nil:

let answer:Double = compute(value: 5.5) ?? 0

I agree with the other posts that optionals are not the right tool for every problem, but you don't need to avoid them. Use if let, guard let, ??, etc. to express how nil values are handled or passed along.