Note: This was written on Swift 2.2 – I’ll update this to Swift 3 when I got extra free time. Plus, if you’re itching to try the code, you could grab the Xcode Playground blog post version (for Swift 2.2) here🙂
As an iOS developer, handling empty value cases in Objective-C is never easy. Let’s suppose we’re making a function that return
NSString instance out of a
Everything seems fine, isn’t it? The method’s logic is pretty clear – it returns the value in
user_token key of the JSON. If the key exists, it will return the string. If not, it will return a
nil value… dead simple, right?
I left out a sanity check there, but let’s continue our example for now.
Suppose that the returned string will be encrypted and stored by C++ library. And for that, we need to cast our
NSString to C string:
Where’s the problem, Do? Everything looks fine…
Right. The method above looks good – it stopped the process early if passed
userToken is nil. Both of them will work correctly, until somebody from the server side single-handedly pass null value in response JSON’s user_token key, instead of omitting it.
Let’s run through the code once again. If the passed JSON is made from
NSJSONSerialization process, the
user_token key will store a
NSNull instance. Thus, the result from
userTokenFromJSON: will be a
NSNull instead of a
NSString – which will allow it to pass through
storeUserToken:‘s early sanity check code (since it’s not a nil), and break the whole app, since
NSNull doesn’t have
Let’s hope this case will never happen in production servers. And yes – I’m looking at you, cowboys.
Due to this issue,
nil-checking alone in Objective-C isn’t sufficient. We also need to ensure whether an instance is the right class using
isKindOfClass: method. It doesn’t always work well either – for example, if the server on the example above returns a number for
user_token value, there’s a chance that it’ll read as
_NSCFString (Apple’s private API) instead of a
That’s why after a few month working with Swift, I grew appreciating the Swift Team’s decision to include Optionals. I believe they made this as an answer to Objective-C’s tedious sanity check. The documentation clearly says that:
You use optionals in situations where a value may be absent. An optional says:
There is a value, and it equals x
There isn’t a value at all.
If I declare a variable to be a
String? (read: String Optional), it would either be a
String value or a
nil. Not a
NSNull, not other class type, and not another Apple’s private API. So,
userTokenFromJSON: above could be rewritten in Swift into this:
And yes, this method will an Optional – either
String or a
nil. 🙂 But the process isn’t ended here – we need to take the available
String value out of the Optional. The term is usually called as unwrapping in Swift development – and there are several ways to do it!
Wait, it seems I had enough rant above… this post started to feel edgy. Let’s change the mood, shall we?
In this post, I’ll list the ways for unwrapping Swift’s Optionals that I have found so far. For the sake of the post, let’s assume we got a new function that needs a
String input and an Optional variable:
Now, we need to unwrap the
name (since it’s a
String optional) to pass it to the
createGreetings(sailorName:). There are several ways to do this: