The nil-coalescing operator is represented by two question marks in Swift. It is one of the operators I miss most when working in Objective-C. The nil-coalescing operator isn't unique to Swift, though. Many languages have a nil-coalescing operator. Some language use the term null-coalescing operator. Let me show you how the nil-coalescing operator works.

Taking a Shortcut

The nil-coalescing operator isn't magical. It is nothing more than a convenience operator. Take a look at this example. We define a constant, author, of type String?.

let author: String? = "Bart"

I honestly like optionals a lot, but they can sometimes lead to verbose code. Take a look the rest of the example. We create a Book object, passing in the value of author.

let author: String? = "Bart"

let book: Book

if let author = author {
    book = Book(author: author)
} else {
    book = Book(author: "Unknown Author")
}

This is valid Swift, but it isn't the most elegant solution in my opinion. We can drastically improve the implementation by making use of the ternary conditional operator. Remember that the ternary operator is an abbreviated version of the if-else statement.

let author: String? = "Bart"

let book = Book(author: author != nil ? author! : "Unknown Author")

This is much better. We reduced six lines into a single line. While this is an improvement, I don't like the implementation because we manually check if author contains a value and, if it has a value, we use the exclamation mark to forced unwrap the value. That is a red flag in my book.

This is where the nil-coalescing operator comes into play. Take a look at the updated example in which the ternary conditional operator is replaced with the nil-coalescing operator.

let author: String? = "Bart"

let book = Book(author: author ?? "Unknown Author")

The nil-coalescing operator is a binary operator, which means it operates on two operands. The expression before the nil-coalescing operator is always of an optional type. In this example, author is of type String?.

The values returned by the expressions before and after the nil-coalescing operator must match. The value stored inside author is of type String. We use a string literal, which is of type String. The type matches the type of the value stored inside author.

The nice thing about the nil-coalescing operator is that it safely unwraps the value of author if it has a value. If author doesn't have a value, the string literal is returned. This is Swift at its best. Right?

Short-Circuit Evaluation

You should know that the nil-coalescing operator uses short-circuit evaluation. Why is that important to know? Take a look at this example.

let value: Record = record ?? fetchRecord()

record is of type Record?. We use the nil-coalescing operator to safely access the value stored inside record. If record has no value, we fetch the record from the database by calling fetchRecord(). It goes without saying that we should only call fetchRecord() if record is equal to nil. That is exactly what the nil-coalescing operator does by using short-circuit evaluation. It does as little work as possible.

If record is equal to nil, fetchRecord() is executed. However, if record is not equal to nil, the value inside record is returned and fetchRecord() isn't executed. You could say that the nil-coalescing operator is lazy by only doing the work that is absolutely necessary.

Optionals Only

I hope it is clear that it makes no sense to use the nil-coalescing operator if the first operand doesn't have an optional value. The compiler won't throw an error, but it will give you a warning as you can see below.

Only use the nil-coalescing operator if you are working with optionals.