Swift Optionals cheat sheet

A summary of Swift optional type expressions.

Optional concept

Optional variables have either a specific value of some base type or nil to represent a not set state, where their value is undefined.

Define an optional type by appending ? to a base type

var i : Int? = 22 // an optional Int, defined
var s : String? = nil // an optional String, not defined 

Force unwrap optionals with ! after a variable

The ! forces a conversion of an optional variable into a value of the corresponding base type, and crashes if the optional variable is nil.

var opt_def : Int? = 10  // an optional integer
var opt_nil : Int? = nil // a nil optional integer

let x1 = opt_def! //unwraps into x1 as Int
let x2 = opt_nil! //crashes: cannot unwrap nil

Fallback unwrapping an optional with ??

The expression a ?? b unwraps the optional value a and returns a! in case it succeeds in unwrapping it, b otherwise.

let name : String? = nil
let actualname = name ?? "Jane Doe" // will have String type

?? is called the nil-coalescing operator.

Implicit unwrapping appending ! to a base type

Optional types can also be defined from a base type appending ! instead of ? to an existing type. The difference is that variables of this type will always be unwrapped without putting ! after their name, and the program will crash if the unwrap fails.

let aname : String! = "John"
let noname : String! = nil

print (aname) // prints John
print (noname) // crashes

The implicitly unwrapped values can however be tested for being nil without crashing, or used in optional binding.

let noname : String! 
if noname != nil {...} // no crash
while let name = noname {...} // no crash either

Chain optionals with ?

When using dot notation to traverse a property hierarchy use the ? after each optional type value. The end result will be nil if any optional in the chain fails to unwrap, otherwise it will be the value of the last element of the chain.

class Store {
    var product: Product?
}

class Product {
    var tag : PriceTag?
}

struct PriceTag {
    var price: Float
}

let s = Store()
var myPrice = s.product?.tag?.price

Note that even if the price property of the PriceTag class is not an optional, the variable myPrice will be of type Float? because it is a result of an optional chain that could fail to unwrap.

Conditional unwrapping with if let

The if let x = opt statement automatically tries to unwrap the value opt, that must be of optional type, into x, that will be a variable of y base type.

func hello( name: String? ){
    if let actualName = name {
        print ("Hello " + actualName) 
    } else {
        print ("Hi! do we know each other?")
    }
}

This concept is called optional binding and can also be used with while loops

Chaining conditional unwrapping

if let statements can be chained by separating them with ,

var opt1 : String? = "ping"
var opt2 : String? = "pong"

if let p1 = opt1, let p2 = opt2 {
    print (p1+p2) //prints pingpong
}

Add an unwrapping condition with where

You can specify a filtering condition in the if let statement itself with the where clause.

var a : String? = "longstring"

if let str = a where str.characters.count >= 10 {
    print (str + " is 10 or more long")
}

Cast to an optional value with as?

Any value can be cast to an optional type with the as? keyword. If the cast fails the result will be nil, otherwise it will have the cast value. The returned variable will have the optional type it is cast to, if that’s not already an optional type.

let i : AnyObject = 10
let s = i as? String // s is of String? type and is nil
let f = i as? Int // f is of Int? type and is 10

Comments