Stacks Image 9

Swift Optional values

What is an optional?

In Swift an optional is a variable that either contains a value, or is missing, that is to say nil (in most languages the term null is used).
As we know this value might be missing at runtime, a safety is put at compile time to ensure we check it has a content before actually using it. The operation that gives us access to the actual value of the variable is called unwrap.

How to declare an optional?

We specify a variable being an optional simply by appending the ? character after its type during the declaration.

  • Non optional: var nonOptional: Int
  • Optional: var optional: Int?

How to unwrap an optional?

There is three way doing so:

  • Using a condition or a guard
  • Using the safe unwrap operator ?
  • Using the force unwrap operator !
  • Using the unwrap with default value operator ??

Unwrapping through a condition or a guard

Inside a condition

if let nonOptional = optional {
    // nonOptional value can be used inside the condition

}

// nonOptional value can't be used after the condition

After a guard:

guard let nonOptional = optional else {
    return // or other exit
}

// nonOptional value can be used after the guard

Unwrapping through the safe unwrap operator ?

This is used to call method on an object only if it is not nil.

myOptionalObject?.myMethod()
// myMethod will be called only if myOptionalObject has an actual value

Unwrapping through the force unwrap operator !

This could be used if we are at least 100% sure the variable does have an actual value. If it does not it will throw a "Unespectdly found nil white unwrapping an Optional value".

While calling a method:

myOptionalObject!.myMethod()
// myMethod will be called without checking if myOptionalObject is nil or not.

While working with a value:

let myComputedValue = compute(myOptionalValue!)

At declaration time, usualy for outlets (links to User interface elements)

    @IBOutlet weak var myLabel: UILabel!
    // myLabel must be an optional because it itsn't accessible at init time, only after the view has been loaded

    override func viewDidLoad() {
        super.viewDidLoad()

        myLabel.text = "No need to unwrap"
        // we use myLabel like if was a non optional value
    }

Without the force unwrap at declaration time we would have written something like:

    @IBOutlet weak var myLabel: UILabel?

    override func viewDidLoad() {
        super.viewDidLoad()

        myLabel?.text = "No need to unwrap"
    }

Unwrapping with default value

This is used to retrieve the actual content of an optional value, or use a default value if it is nil.

Lets look at this example:

var myOptionalValue: Int?

// somecode where myOptionalValue might got a value or remain nil

let myNonOptionalValue = myOptionalValue ?? 2

It is a shorter equivalent to:

var myOptionalValue: Int?

// somecode where myOptionalValue might got a value or remain nil

let myNonOptionalValue: Int
if let unwrapped = myOptionalValue
  myNonOptionalValue = unwrapped
else
  myNonOptionalValue = 2