I understand how "!" or "?" works. But i'm not quite sure what the added benefit is compared to != nil checking. What is the added benefit of moving to "!?"? I feel like it's just something Apple has added but can't really see the extra benefit compared to status quo of iOS. Am i missing something here? Thanks in advance.
The difference between checking for nil and requiring an optional being unwrapped can amount to the difference between your code crashing or not. Optionals, when used correctly, can both increase safety and make your code more readable.
Suppose you have an array, and you want to get out the first value in it. You might do it like this:
if !arr.isEmpty {
useValue(arr[0])
}
But of course, it’s easy to forget that isEmpty
part, and if you do, your code will crash with an out-of-bounds error.
So intead, there’s a much better way: use the array's first
method, which returns an optional with nil
if the array is empty:
if let val = arr.first {
useValue(val)
}
With this form, you cannot get this wrong. It’s impossible to use the arr. first
value without unwrapping it. If you forget, you get a compilation error. It’s also more readable to my eyes/
Presumably you would expect your != nil
formulation to work something like this:
if arr.first != nil {
// all optionals would be “implicit”
useValue(arr.first)
}
Putting aside that you’re calling .first
twice which is a bit inefficient, and the question of type compatibility, essentially this lands you back to square one – you could forget to do the nil
comparison, and then, kaboom. Or, you could take the Objective-C approach and say nil
is fine to send messages to – but that also leads to all kinds of confusion (personally I hate the idea of an implicit sending messages to nil meaning no-op), and also leads to the question, what do you do when the function returns a value type such as an Int
. Must everything be nullable? This leads to much mess in Obj-C land.
What’s more, there are all sorts of conveniences you can introduce once you are dealing with optionals, such as nil-coalescing:
// default to 0 if no first element
arr.first ?? 0
// much neater than this equivalent form:
arr.first != nil ? arr.first : 0
or optional comparison:
// will only be true if arr is non-nil and zero
if arr.first == 0 {
}
For more examples, see this answer
The ?
operator is very convenient, when it comes to chaining, e.g.:
a?.b?.c?.doSomething()
Otherwise you would have to check a
, b
and c
for nil
, which may result in more unreadable code than chaining does.
Another thing is, that you can easily mark arguments being optional, e.g.
func someFunc(arg: Type?)
and it is immediately clear, that this is a type which may be nil
, i.e. the language enforces this. Otherwise you would pass something which could be nil
and you forget the check and experience crashes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With