Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. SwiftBeginner - About nil and Optionals

About nil and Optionals - Images: Japanese

Hey there, everyone! Hope you're doing well.

I'm writing this article in early November, and it's gotten suddenly cold outside. After spending x0 years doing desk work, my body just can't keep up with these dramatic temperature swings.

Alright, let's move on to nil and Optional types.

Before we dive in, a word of caution about 'nil'. Other programming languages have 'nil' or 'null' values too, so if you're familiar with those, you might assume Swift's 'nil' works the same way — but it's actually quite different in structure. Getting this wrong will send you down a rabbit hole, so be careful. (Yes, it happened to me too.)

Let's take a quick look back at what we've covered so far. Check out this sample:

var n: Int

This just declares a variable n of type Int. It has no value inside. Now if you try to output this variable n with print(), here's what happens:

var n: Int

print(n) // This is an error.

Yep, it throws an error. The error basically means "you're trying to output something that doesn't exist."

This is how the computer world works — trying to do something with a value that doesn't exist causes an error. Computers are built to perform precise, physical calculations, so handling "things that don't exist" is a bit of a weak spot. This applies to other programming languages too — it's been this way forever.

That said, when writing programs, you often need to handle situations where a value "might not exist." That's why almost every programming language provides some way to deal with non-existent values.

In Swift, the standard way to handle "something that might not exist" is to use an Optional type.

Let's give Optional types a try. To define something as an Optional type, you write 'Optional<DataType>' like this:

var n: Optional<Int>

Variable n is still empty, just like before. Now let's try outputting it with print():

var n: Optional<Int>

print(n) // Outputs 'nil'.

Notice the difference? Last time it threw an error, but this time it outputs nil without any error at all.

When you wrap data in an Optional type, it returns 'nil' when no value exists — which lets you avoid the error. That's the basic usage of Optional types.

One small but important note: in the example above, the correct mental model is not "defining an Int with Optional features" but rather "wrapping an Int value inside an Optional." It's a subtle distinction, but easy to get mixed up, so keep it in mind.

In programming, you'll often hear the phrase "returns a value." This means "the expression gives back (tells you) the result of a calculation."

Let's think back to basic math. Say you have this expression:

1 + 2

The answer is 3, and in programming we'd say "the expression '1 + 2' returns 3."

Think of a math "expression" as a "function," and the "answer" as the "value" — that's roughly the analogy.

It's a small nuance, but it can be confusing if you're not used to programming. If you get lost, try mapping it back to a simple arithmetic expression — that tends to make it click.

Now, there's another type in Swift that's similar to Optional but a little different — let me introduce it.

It's called 'Implicitly Unwrapped Optional type'. Just like Optional, it returns 'nil' when there's no value inside.

Quite a mouthful, isn't it? Translated to plain English, it means "an Optional type that gets 'unwrapped' automatically."

We'll get to what "unwrap" means in a moment — first, let's look at how to define it:

var n: ImplicitlyUnwrappedOptional<Int>

Writing 'ImplicitlyUnwrappedOptional<DataType>' like this defines a value wrapped in an Implicitly Unwrapped Optional type.

There's also a handy 'syntax sugar' shorthand for both Optional and Implicitly Unwrapped Optional. Check out this sample:

The following has variable 'n' defined as Optional, and variable '_n' as Implicitly Unwrapped Optional:

var n: Int? // Optional type.

var _n: Int! // Implicitly Unwrapped Optional type.

Notice the ? and ! attached after Int.

Writing 'DataType?' gives you an Optional type, and 'DataType!' gives you an Implicitly Unwrapped Optional type.

Writing Optional<DataType> or ImplicitlyUnwrappedOptional<DataType> every time is a chore, so using ? or ! is the standard practice.

Syntax sugar in programming refers to an alternative, more concise notation for something that already exists in the language.

In this case, 'Optional<DataType>' can be written more simply as 'DataType?' — that's what syntax sugar is all about.

It comes up in textbooks fairly often, so it's worth remembering.

Now let's look at some things to watch out for when using Optional types. Take a look at this sample:

var n: Int? = 1

var _n: Int = 2

Here we have 'n', an Int wrapped in Optional, and '_n', a plain Int.

Since both are Int, you'd expect to be able to add them — but try it and something surprising happens:

var n: Int? = 1

var _n: Int = 2

print(n + _n) // This is an error.

Look at n + _n. You might expect 3 to be output, but it errors out instead.

The reason: one of them is an Optional type, and you can't perform arithmetic on it as-is.

Some other languages have "implicit type conversion" — where type changes happen behind the scenes without the programmer noticing — so you might be able to compute directly. But Swift is designed with the philosophy of "no implicit type conversion," so the above doesn't work.

That means when you need to compute with data defined as Optional, you sometimes need to convert it back to its original form first. That conversion is called 'unwrapping'.

Let's unwrap the variable from before so we can do the arithmetic. To unwrap an Optional type, do this:

var n: Int? = 1

var _n: Int = 2

print(n! + _n) // Outputs '3'.

Look at n! + _n. Variable n now has ! attached to it.

By adding ! to a variable like this, you unwrap the data and restore it to its original type.

By the way, we saw ! earlier as the syntax sugar for ImplicitlyUnwrappedOptional<DataType>.

It can get confusing, but here's the rule: '!' attached when defining a variable is the syntax sugar for 'ImplicitlyUnwrappedOptional<DataType>'; '!' attached to an already-defined variable is an unwrap operation.

It's easy to mix these up since it's the same symbol — don't get them confused. Even I catch myself thinking "wait, which one is this?" sometimes.

var n: Int! = 1 // This '!' is the syntax sugar for 'ImplicitlyUnwrappedOptional<DataType>'.

print(n!) // This '!' is an unwrap.

So remember: when using a variable defined as Optional, you need to unwrap it first.

That said, unwrapping every single time is a bit of a hassle. When you find yourself wishing the language would just handle things for you automatically, that's what Implicitly Unwrapped Optional is for.

Let's try using ImplicitlyUnwrappedOptional from earlier. This time, let's use ! instead of ? when defining the variable. Watch what happens:

var n: Int! = 1

var _n: Int = 2

print(n + _n) // Outputs '3'.

Look at n + _n. Even without explicitly unwrapping with !, the arithmetic works just fine.

This is because Implicitly Unwrapped Optional automatically unwraps itself when used — it's like an Optional type that unwraps on its own.

If you know you'll always be unwrapping a particular variable, defining it as Implicitly Unwrapped Optional makes life easier. Use whichever fits the situation.

So far we've seen '!' for unwrapping, but you can actually unwrap with '?' as well. Take a look:

var s: String?

This defines a variable 's' wrapping a String in an Optional type. Since it's Optional, 's' might be 'nil'.

Quick side note: Swift's String type has a .characters.count property that lets you count the characters in a string.

You write it as someString.characters.count, and it returns the character count as an Int. Like this:

print("".characters.count) // Outputs '0'.

print("abc".characters.count) // Outputs '3'.

Now, imagine using '.characters.count' on the Optional-wrapped String variable 's' we defined above.

If s has some string in it, .characters.count works fine — but what if s is nil?

That would give you nil.characters.count, and since nil doesn't have .characters.count, you'll get a hard error.

var s: String?

s = "abc" // Assign a string.

print(s!.characters.count) // OK. Outputs '3'.

var _s: String?

print(_s.characters.count) // Error, because '_s' is nil.

print(_s!.characters.count) // Still an error even after unwrapping with '!'.

In situations like this, use '?' instead of '!'. When you unwrap with '?', if the unwrapped value is 'nil', the rest of the expression is skipped and 'nil' is returned — so the error is avoided. Like this:

var s: String?

print(s?.characters.count) // 's' is nil, so the rest is skipped and 'nil' is output.

s = "abc" // Assign a string to 's'.

print(s?.characters.count) // 's' is not nil, so '.characters.count' runs and outputs 'Optional(3)'.

Using ? like this makes it easy to build escape logic for when a value is nil. It's really handy, so keep it in mind.

A quick note about using '?': it's a syntax for accessing a property or calling a method on Optional data.

We haven't covered properties and methods yet, so this might feel a bit abstract — but any time you're chaining something like .characters.count after a variable, you can go ahead and use ?.

var s: String? = ""

print(s?.characters.count) // OK.

But writing just s? on its own is not valid:

var s: String? = ""

print(s?) // Not valid.

Don't mix these up. When I was first learning this, I genuinely had a "?" moment over this exact thing.

There's one more thing to watch out for: look at the last print(s?.characters.count) output in the earlier sample. Instead of the number 3, you got Optional(3), right?

When you use '?', what comes back is the data before unwrapping, not the unwrapped value. So code like this will error out:

var s: String? = "abc"

print(s?.characters.count + 10) // Error.

The reason: 's?.characters.count' returns Optional data, and you can't add a plain Int '10' to it directly.

You'd need to unwrap it with '!' first, like this:

var s: String? = "abc"

let n = s?.characters.count // Capture it in a constant first.

print(n! + 10) // Outputs '13'. The key is unwrapping with '!'.

This is another easy mistake, so watch out for it.

Also, be careful about what happens when variable s in the example above becomes nil.

Since 's' is Optional, it can become 'nil' — which means 'n! + 10' could turn into 'nil! + 10', and that'll instantly throw an error.

var s: String? // 's' has no value assigned, so it's nil.

let n = s?.characters.count // 'n' gets nil.

print(n! + 10) // Becomes 'nil! + 10', so this is an error.

So it's good practice to always write branching logic for when 'nil' might show up.

That's where the ?? operator comes in handy. It lets you branch based on whether a value is nil. Here's how it works:

var s: Int?

print(s ?? "it's nil") // Outputs "it's nil".

Focus on the (s ?? "it's nil") part.

?? is an operator that works like this: "if the left side is nil, return the right side; if the left side is not nil, return the left side."

In this case, 's' is Optional and hasn't been assigned anything — so it's 'nil' — and the string on the right, "it's nil", gets output.

Now let's assign a value to 's' and see what changes:

var s: Int?

print(s ?? "it's nil") // Outputs "it's nil".

s = 1

print(s ?? "it's nil") // Outputs '1'.

This time 1 is output.

That's the ?? operator in a nutshell. It's pretty useful, so give it a try when the occasion calls for it.

The '?' we introduced earlier — the one that escapes when the value is 'nil' — is officially called 'Optional Chaining'.

var s: String? = "abc"

let n = s?.characters.count // This '?' is Optional Chaining.

print(n! + 10) // Outputs '13'.

It shows up in textbooks occasionally, but since it's essentially just "the ? that escapes on nil," you don't really need to memorize the name.

Also, there's something called an if statement that we'll cover in a later article — and you can use it to branch based on whether a value is nil. Like this:

var s: String?

if s != nil {
    print("not nil.")
}
else {
    print("it's nil.")
}

If you're coming from another language, this style might feel more natural.

Using an if statement and a constant together to branch on whether something is nil is called Optional Binding. You don't necessarily need to memorize the name either, but it's worth knowing it exists.

And that wraps it up! This was a pretty complex topic and ended up being quite long — hope you're still with me.

In the next article, we'll get into functions and more. Until then, take care — see you next time!

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .