Don of the Day

Don of the Day


Adventures in software development with Xamarin and the Web

Software developer, building things with code in sunny Scottsdale, AZ.

Share


Twitter


Swift Optionals

Don FitzsimmonsDon Fitzsimmons

Continuing my series exploring the Swift language from the perspective of a C# developer, I left off with some strange syntax in Swift involving lot's of !? intermingled with some expressions. What is this excessive use of punctuation and why is it there? For instance:


let awesomeConstant: String? = "I have no purpose"
print(awesomeConstant)

//prints Optional("I have no purpose")

So we've introduced this question mark after the type declaration of our meaningless constant. That basically means that the constant, awesomeConstant, is the type of optional string. So, if we try to print the value of the constant, we don't get the string, we get the optional. In order to get the value of the constant, we have to unwrap the optional, which looks like this:


let awesomeConstant: String? = "I have no purpose"
print(awesomeConstant!)

//prints "I have no purpose"

This is called "forced unwrapping". Using the exclamation point, we're telling the runtime to extract the value from the optional in the constant. If the constant has no value, we get a runtime error.

If you're a C# developer and you're looking at this, you're thinking, "Oh, yeah, this just like nullable types in C#." Sort of. The difference is that unlike nullable in C#, optionals are used everywhere in Swift and for good reason.

With C#, most of the types we use are reference types and those types can be null. We also have value types, like int, double, float, etc, and these types cannot be null. The must have a value. So, if you need to make a C# value type null, you can use the handy nullable type by also using a question mark in its declaration.


int? awesomeInteger = null;

Console.WriteLine(awesomeInteger);

//prints nothing because it's null

What really happens when you use that int? syntax? It's really just a way of wrapping the value type int in a Nullable type. It's nothing fancy, just a convenient way of allowing nullable value types.

In swift, variables and constants are all considered value types, which means they all need to be initialized and have some value. This is why Swift relies so much on optionals. Optionals allow you to create a variable or constant even if you don't have a value to assign it. Instead, you make it an optional. So the code below is valid:


let awesomeConstant: String?
awesomeConstant = "I have no purpose"

print(awesomeConstant!)

//prints I have no purpose

This time, awesomeConstant was not initialized with a value, but it was declared as an optional. Then we set it's initial value and where able to force unwrap it because it does in fact have a value. Again, if we did not assign it a value, it would cause a runtime error. There's another, safer way to do this. But before we get to that, C# has some new syntactic sugar for us that looks very similar to this force unwrapping:


//pre-C# 6.0
var someObject = new PretendObject();

if (someObject != null) //we have to check if it's null before accessing it
    Console.WriteLine(someObject.fakeProperty);

//C# 6.0 null conditional operator
var someObject = new PretendObject();

Console.WriteLine(someObject?.fakeProperty);

That feels similar to what Swift is doing and does work similarly. It gets us away from doing conditional null checks all over the place in a nice concise manner.

Back to unwrapping optionals in a safe way. This example is straight from the Apple documentation and illustrates how it's done and it's very similar to the way a C# developer would use conditional null checks:


class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person()

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

The key point to all of this: Swift treats constants and variables as value types. Because of this, declaring a constant or variable requires a value assignment. If you don't happen to have a value, you can make the type optional and check it for a value when accessing it. Optionals are a critical piece of learning Swift and used throughout Apple's frameworks.

Dig into the nitty gritty of optionals here.

Software developer, building things with code in sunny Scottsdale, AZ.

Comments