Fatal error: Unexpectedly found nil while unwrapping an Optional value

tl;dr: Swift does not like when you try to access something that doesn’t exist (nil) and will crash if you try to access nil in any way: reading/writing a property that is nil, calling a function when the target is nil. Always use if/let or guard or nil-coalescing ??. The official Swift Language guide’s Optional Binding section covers it nicely.

Tell Me More… about Objective-C

If you’ve read about it, you’re already aware that everyone says Objective-C is a dynamic language or that it’s very flexible. That makes sense, but what does that even mean?

One aspect of flexibility is handling nil without crashing. Unlike Swift, Objective-C’s nil is not opt-in. It exists as part of the language itself. For example, a very simple way to crash a Swift program would be accessing an optional whose value is currently nil.

This will crash the playground/app with an EXC_BAD_INSTRUCTION error.
Swift allows me to opt-in to use nil by calling the ! operator which forces the optional open.

The following code will not crash the Obj-C runtime.

In Objective-C, I can absent-mindedly pass nil to my functions or set it to my properties because we aren’t even handling the instances ourselves: we’re handling pointers. Pointers can naturally end up being nil because they are not the object themselves.

What’s funny about all this is that Objective-C ends up with some interesting idioms that wouldn’t be possible in Swift. For example, trying to check for nullability in Swift is such a big deal that there’s plenty of ways of doing it.

  • if/let: if let string = swiftString { }
  • guard: guard let string = swiftString { }
  • nil-coalescing: let string = swiftString ?? ""
  • optional chaining: swiftString?.count

It’s all about making sure nil doesn’t get mixed up with our regular values. Swift makes nil the enemy and with good reason. It complicates matters greatly by adding an additional state to every value in your program!

On the other hand, Objective-C embraces nil. Instead of using any of the above 4 ways of unwrapping, we can do a quick check like so:

Yes, we’re checking if ! on an NSString.

This idiom is actually super common and very useful… once you get used to the absurdity of it. Since Objective-C will always handle pointers, what you’re actually checking is that the pointer is not nil. A pointer is simply an address in memory (e.g. 0x7fffe9ebf984 is a 32-bit pointer), so if our NSString pointer is nil, then its address must be 0x000000000000). Neat!

Not only that, but sending a message (a blog post for another day) to our NSString will not only be accepted by the program, it will return nil back.

We called uppercaseString on nil and nil returned nil back.
There’s a yo dawg joke in there somewhere.

And this makes programming a breeze! You can just pass around nil willy-nilly. If you ever make a mistake by unexpectedly passing nil around, Objective-C will fail silently and I know you will not believe me but it feels amazing. That feeling of being able to worry about things other than if/let, guard let, ?, ??, ! is just liberating.

It’s flexible. That’s what it is. It’s very flexible.

Don’t get me wrong, there’s plenty of things wrong with it too. Sometimes your program would just not do what you expected. Say you clicked on a button or tapped on a switch and nothing would happen and then you’d have to go around debugging who was receiving nil and silently failing.

But there’s an elegance to it that I cannot find in Swift. Maybe it’s just me and maybe it’s because Objective-C was only my first “professional” language. My first job was in 2010 as an iOS developer so all I could do was learn Objective-C and learn it I did.

Either way, that’s enough Objective-C talk for today.

This is a series I started because I love Objective-C. However, I also love Swift! If you love Swift like me, you may like my weekly newsletter where I send you a 15-minute Swift exercise, and have additional sections like interviews from members of our community, junior developer spotlights and more.


* indicates required