Primative datatypes (Ints, Strings, Floats, etc) can't store nil values, as is the same in any other object oriented programming language:
But in Swift, even object references can't store nil:
That's where Optionals are useful. If you have a variable that could have a nil value, then it should be declared as an Optional. You're giving it the option of either having a value, or having no value.
For example, in some cases a method can't return a value. Below, the Int() initializer could work for one string, s1, but wouldn't for the second string, s2:
as it's impossible to convert "abc" to an Integer. Since y needs the option to have no value, we should declare it as an Optional. We can do so by adding a "?" after the datatype declaration:
which removes the compiler errors.
Another example of when an Optional would be necessary are for properties that cannot be initialized when an object is constructed. For example:
What's happening here? Because we're adding the button property, and it's a regular Swift variable, and Swift variables can't store nil values, the compiler gives us the error message "Class ViewController has no initializers". Again, by declaring button as an optional, by adding the "?" after UIButton, Swift then knows that it could store a nil value.
Unfortunately, once you declare an Optional, you can't use it unless you find out what it is. Does it have a nil value or not? In order to find out, you need to unwrap it first.
If you don't unwrap it, and try to use it, you may see an error like this:
You could just follow the compiler's suggestion to add a "!" to unwrap y, but that does not safely unwrap the variable, and could lead to an app crash if the variable does have a nil value. To safely unwrap the variable, we'll want to use an "if let" or "if var" statement. In the example below, we'll be changing the value, so we'll want to use "if var":
We've safely unwrapped the variable, and can handle the case where the value is nil. The only time you should unwrap using "!" is when you're 100% sure that the value will not be nil. Otherwise your app with crash.
To access the properties of Optional object, you'd normally need to do something like this:
first unwrapping the image using the "if let" statement, then accessing the size property. With Optional chaining, you're able to unwrap the image object using the "?" notation, and access the size property in one line:
As you can see, this is a slightly more efficient way to unwrap an object and access a property.