Nil value
Before exploring optionals it's imporant to understand the concept of nil
(or "null" in other languages).
As you know, when we declare a variable we need to assign an initial value, however, what if we don't assign any value, ΒΏis that possible? In case we don't assign any value to a variable we can say that its value is nil
.
How to assign a nil value
When we declare a variable, we can't assign a nil
value to it unless we mark this variable as Optional. To make this we just need to add a ?
next to the type:
struct Person {
var name: String
var age: Int?
}
Now when we initialize a Person
object, we can assign nil
to age
.
var me: Person = Person(name: "Pablo", age: nil)
Why do we need an optional value?
We can declare some variables as Optional when the value of this is not required, for example, when we ask a user for his personal info we could decide that his name is required, but not his age.
Unwrapping an optional
Unlike normal variables, in case of the Optional variables we need to "unwrap" its value if we want to access to it. There are a few ways to do this:
1. ??
If you use an Optional variable with a Text
you'll realise that the output won't be what you expected.
var me: Person = Person(name: "Pablo", age: 23)
struct Person {
var name: String
var age: Int?
}
var body: some View {
Text(me.name)
Text("\(me.age)")
}
You can see "Optional(23)" on the screen. This is because when we added the ?
symbol, we converted our Int
variable to an Optional
variable that stores an Int
. So if we want to show the age we need to unwrap it. To do this we can use the command ??
followed by a default value that will be used in case that age
is nil
. This default value's type should be the same as age
.
var me: Person = Person(name: "Pablo", age: 23)
var you: Person = Person(name: "Andrea", age: nil)
struct Person {
var name: String
var age: Int?
}
var body: some View {
Text(me.name)
Text("\(me.age ?? 0)")
Text(you.name)
Text("\(you.age ?? 0)")
}
2. if let
We can check if the value is nil before using any component. With the command if let
we can define a code block as we do in a standard if
.
var me: Person = Person(name: "Pablo", age: 23)
var you: Person = Person(name: "Andrea", age: nil)
struct Person {
var name: String
var age: Int?
}
var body: some View {
Text(me.name)
if let age = me.age {
Text("\(age)")
}
Text(you.name)
if let age = you.age {
Text("\(age)")
}
}
The main difference with this is that the age's Text
won't be created when age
is nil since its code block won't be executed, otherwise, a new local Int
variable called age
will be created and will be available to use it in our Text
.
age
on both if let
because this local variable only exists inside the if let
block, so they don't conflict to each other.
3. Optional chaining
Let's see a similar example, but defining our Person
variables as Optional instead of the age
.
var me: Person? = Person(name: "Pablo", age: 23)
var you: Person? = nil
struct Person {
var name: String
var age: Int
}
var body: some View {
Text(me?.name ?? "No name")
Text("\(me?.age ?? 0)")
Text(you?.name ?? "No name")
Text("\(you?.age ?? 0)")
}
If we want to access any Person
property we need to put a ?
first. This will make that, in case the value is nil, it will fall in the default value.
Be the first to comment