Some big picture perspective to add to the other useful but more detail-centric answers:
In Swift, the exclamation point appears in several contexts:
- Forced unwrapping:
let name = nameLabel!.text
- Implicitly unwrapped optionals:
var logo: UIImageView!
- Forced casting:
logo.image = thing as! UIImage
- Unhandled exceptions:
try! NSJSONSerialization.JSONObjectWithData(data, [])
Every one of these is a different language construct with a different meaning, but they all have three important things in common:
1. Exclamation points circumvent Swift’s compile-time error handling checks.
When you use !
in Swift, you are essentially saying, “Hey, compiler, I know you think an error could happen here, but I know with total certainty that it never will.”
(Edit to clarify: The force-unwrapping !
is still “safe” in the language design sense that is it not undefined behavior, and is guaranteed to crash in a clean, predictable way (unlike dereferencing a null pointer in C or C++). It is not “safe” in the app developer sense that the language makes sure your app won’t suddenly fail because of your bad assumptions.)
Not all valid code fits into the box of Swift’s compile-time type system — or any language’s static type checking, for that matter. There are situations where you can logically prove that an error will never happen, but you can’t prove it to the compiler. That’s why Swift’s designers added these features in the first place.
However, whenever you use !
, you’re ruling out having a recovery path for an error, which means that…
2. Exclamation points are potential crashes.
An exclamation point also says, “Hey Swift, I am so certain that this error can never happen that it’s better for you to crash my whole app than it is for me to code a recovery path for it.”
That’s a dangerous assertion. It can be the correct one: in mission-critical code where you have thought hard about your code’s invariants, it may be that bogus output is worse than a crash.
However, when I see !
in the wild, it's rarely used so mindfully. Instead, it too often means, “this value was optional and I didn’t really think too hard about why it could be nil or how to properly handle that situation, but adding !
made it compile … so my code is correct, right?”
Beware the arrogance of the exclamation point. Instead…
3. Exclamation points are best used sparingly.
Every one of these !
constructs has a ?
counterpart that forces you to deal with the error/nil case:
- Conditional unwrapping:
if let name = nameLabel?.text { ... }
- Optionals:
var logo: UIImageView?
- Conditional casts:
logo.image = thing as? UIImage
- Nil-on-failure exceptions:
try? NSJSONSerialization.JSONObjectWithData(data, [])
If you are tempted to use !
, it is always good to consider carefully why you are not using ?
instead. Is crashing your program really the best option if the !
operation fails? Why is that value optional/failable?
Is there a reasonable recovery path your code could take in the nil/error case? If so, code it.
If it can’t possibly be nil, if the error can never happen, then is there a reasonable way to rework your logic so that the compiler knows that? If so, do it; your code will be less error-prone.
There are times when there is no reasonable way to handle an error, and ignoring the error — and thus proceeding with wrong data — would be worse than crashing. Those are the times to use force unwrapping.
I periodically search my entire codebase for !
and audit every use of it. Very few usages stand up to scrutiny. (As of this writing, the entire Siesta framework has exactly two instances of it.)
That’s not to say you should never use !
in your code — just that you should use it mindfully, and never make it the default option.