Swift Optionals

Share the joy
  •  
  •  
  •  
  •  

Swift optionals are a way to indicate the absence of a value for any type. In Objective C you would use nil, however that only worked for objects, not for structs or enumerations or basic C types like int. For these types you would have to use a convention, so the developer would know that -1 means missing value or the method returns NSNotFound or NULL or something else completely. Swift optionals avoid the situation where you need to remember what the convention is and just have 2 states: there is a value and it equals x or there isn’t a value at all. The implication of this is that in Swift all values are guaranteed to be non-nil. If you know a value might be missing, just wrap the type of the value in an optional type.

To declare a Swift optional you use the ? symbol like this:

var optionalString: String?

At this point, the value of optionalString is nil. However, there is a difference between Objective C’s nil and Swift’s. In Objective C, nil is a pointer to a non existing object. In Swift, nil is not a pointer, it just indicates the absence of a value of a certain type.

You can assign a value to your optional in the normal way:

optionalString = "Hello"

and then if you want to make it have no value at all you just set it to nil:

optionalString = nil

Make sure you only use nil for optional types. If you try to assign nil to a non optional type you will get a compiler error.

Unwrapping optionals

Before you can use an optional you need to check if it has a value and if yes you need to
unwrap that value. If an optional has a value, it evaluates to true; if it doesn’t it evaluates to false. If you know that an optional has a value you can access that value by adding ! to the end of the optional’s name. This is called forced unwrapping.

Let’s create an enum of colours and a method that returns an association for some colours and no association for others.

enum Colors
{
    case Red
    case Blue
    case Green
    case Pink
    case Gray
}

func colorAssociation(color: Colors) -> String?
{
    switch color {
    
        case .Red:
            return "fire"
        case .Blue:
            return "clear sky"
        case .Green:
            return "forest"
        default:
            return nil
    }
}

Notice that the method returns an optional. We can use the value returned by this method like this:

let firstColor = colorAssociation(Colors.Red)

if firstColor {
    println("This colour is like \(firstColor!)")
} else {
    println("I can't think of anything similar")
}

Always check if the optional has a value before using !, otherwise you will get a runtime error.

Optional binding

Optional binding is the combination of checking whether an optional has a value and assigning the unwrapped value to a constant or variable. You can use it with if or while, with constant or variables:

if var secondColor = colorAssociation(Colors.Gray)
{
    secondColor = "Nice colour like " + secondColor
    println(secondColor)
} else {
    println("I can't think of anything similar")
}

 

Implicitly Unwrapped Optionals

If you have a value that will be nil for a while before it is initialised, but after that it is never nil again, then you can use implicitly unwrapped optionals. With simple optionals you can set a value, then set the optional to missing value (nil), then set another value, then nil again. With implicitly unwrapped optionals you can have a missing value for a while, but after a value is set you will never get back to nil again.

var optionalNumber: Int? = 34
println(optionalNumber!)
//exclamation mark needed to unwrap the value


let unwrappedOptionalNumber: Int! = 22
println(unwrappedOptionalNumber)
//no need to force unwrap the value, it is done automatically

The nice thing about implicitly unwrapped optionals is that you don’t have to check for nil or unwrap the value yourself but you still get all the safety features of optionals. You can check if an unwrapped optional contains a value and use optional binding. Implicitly unwrapped optionals are used throughout the API calls we know from Objective C. UIKit has lots of examples of this:

func titleColorForState(_ state: UIControlState) -> UIColor!

var attributedText: NSAttributedString!

func dequeueReusableCellWithIdentifier(_ identifier: String!,
    forIndexPath indexPath: NSIndexPath!) -> AnyObject!

 

Optionals chaining

Let’s imagine the following scenario:

class Photo {
    func displayPhoto() {
       //display photo on screen
    }
}

class Car {
    
    func carPhoto() -> Photo? {
        return Photo()
    }
}
class Person {
    
    var car: Car?
}

For a given person, we want to display a photo of her car, if she has a car and the car knows how to give us a photo. We’ve seen that in order to use optionals (both the car property and the method that returns the car photo use optionals) we need to unwrap them first. So the code would look something like this:

let x = Person()

if let car = x.car {
    if let photo = car.carPhoto() {
        photo.displayPhoto()
    }
}

This looks like too many ifs and we aren’t even going that deep in the class hierarchy. Fortunately there is a better way and that is optionals chaining. You add a ? after the optional value on which you wish to call a property or method. If the optional is nil then the chain stops there, if it has a value then the call succeeds. So we can rewrite all that code like this:

x.car?.carPhoto()?.displayPhoto()

Using the ? is very similar to using ! for forced unwrapping. The main difference is that optional chaining fails gracefully if the optional is nil, while forced unwrapping would result in a runtime error.

This is a very cool feature, however there are a few things that you need to remember when using it. The most important thing to remember is that the result of an optional chaining call is always an optional, even when the property or method you are calling returns a non-optional value.

If we add an engine variable to our car, which isn’t an optional:

var engine: Engine = Engine()

and we use optional chaining to get the engine, the result is Engine?, not Engine as you might expect. So in order to use the value you can use optional binding as usual:

if let engine = x.car?.engine {
    println("car has an engine")
}

Even when you call a method that doesn’t specify a return type, you still get back an optional. If a method doesn’t specify a return type then by default the return type is Void. If you call the method by using optional chaining like we did with the displayPhoto() method, the return type is Void?. This means you can check if a method call was successful even if that method doesn’t specify a return type.

Optionals seem like a nice feature. If you remember these 2 things then you’ll be fine while using them:

  1. you need to unwrap the value before using it
  2. when using optionals chaining remember that what you get back is an optional, regardless of what the type of the property or the return type of the method you’re calling is

If you want to learn more about it the best resources are the Intermediate Swift WWDC video and the Swift book.

Enjoy Swift coding!

 


Share the joy
  •  
  •  
  •  
  •  

Leave a Reply

Your email address will not be published. Required fields are marked *

*