What are Optionals in swift ?

If you are an iOS developer, you probably might have came across swift language . Most of you might have became an expert in swift by this time.
When I started learning swift it was difficult to understand optionals in swift. So, let’s understand what they are.
Optionals are a fundamental part of swift coding. Keeping it simple, we can say that optionals help us to separate good code from bad code and hence prevent crashes.
Different programming languages uses different preventive measures to avoid a crash. But most of them are helpless in most of the cases. Swift however is more practical in this case and optionals will help you to make your code crash free. Well that’s not 100 percent true, but however it will help you to make a much better code.
Optionals either hold no value or hold some value. Optionals allow storingnil, a.k.a absence of value.
The Optional type is an enumeration with two cases. Optional.none is equivalent to the nil literal. Optional.some(Wrapped) stores a wrapped value.
In short, optional is an generic enum. For easy understanding, have a look at the following code:
from apple docs
SO, optional is a generic enum with 2 cases, none and some<wrapped>and some methods. Please refer apple docs for more in depth explanation.
So, lets get started. Open your xcode and create a new playground. Let’s start swifting.
//: Playground - noun: a place where people can playimport UIKitvar numberOfCrashes : Int?
Just have a look at the above code. The question mark (?) at the end denotes that it is an optional variable. If you see a question mark at the end of a variable declaration, just understand that it may or may not contain a value in it. So, at some part of your program, you don’t know if there is a value or not for a variable, then mark it as optional.
Now, try to print the value of the variable ‘numberOfCrashes’.
print(numberOfCrashes!)
The exclamation point (!) at the end of the variable is used to unwrap the value. At this point, the code will crash. That is because, you just force unwrap an optional variable with no value in it. You just took an optional variable and said “hey! ,give me the value out of it”, and you try to use it. But if you do this, and there is no value in the variable, then your program will crash.
//: Playground — noun: a place where people can playimport UIKitvar numberOfCrashes : Int?numberOfCrashes = 3print(numberOfCrashes!)
But if you set a value to the variable before you force unwrap the value, the code will not crash. But this way you are actually abusing the optional variable. You will not be lucky like this every time. But this is bad coding practice.
What do we do now? May be we should do a nil check before we force unwrap an optional.
//: Playground — noun: a place where people can playimport UIKitvar numberOfCrashes : Int?if numberOfCrashes != nil {print(numberOfCrashes!)}
Now your code will not crash as you are force unwrapping it the optional variable only after a nil check.
The swift way of doing the nil check is by using a if let statement(Optional binding.. mentioned later in this article).
//: Playground — noun: a place where people can playimport UIKitvar numberOfCrashes : Int?if let crashCount = numberOfCrashes {print(crashCount) // same as print(numberOfCrashes!)}
The above method will check if the optional variable ‘numberOfCrashes’ contains some value or not. If exists, then it will be copied to a constant called crashCount and then only the code block will get executed.
Anytime you see an optional variable with a question mark, then use the if-letstatement to make sure it’s not nil.
The answer is YES!!. But in most cases, it will be useless as the scope of the variable will be inside the if block only.
Note: If you define an optional variable without providing a default value, the variable is automatically set to nil for you:
var surveyAnswer: String?// surveyAnswer is automatically set to nil

Unwrapping optionals

It can be done in a few ways:
◙ Force unwrapping
◙ Implicit unwrapping
◙ Optional binding
If you defined a variable as optional, then to get the value from this variable, you will have to unwrap it. This just means putting an exclamation mark at the end of the variable. This way of unwrapping by directly putting an exclamation mark at the end while accessing is called Forced unwrapping.
Forced unwrapping is error prone and is not recommended.
var myString:String?
myString = "Hello, Swift!"let x = myString! // forced unwrapping Success!!!//_______________________________var myOtherString:String?
let x = myOtherString! // forced unwrapping Error. The value is not set.
An Implicitly Unwrapped Optional is an optional that doesn’t need to be unwrapped because it is done implicitly. These types of optionals are declared with an (!) instead of a (?). The only change is that this time the compiler will not yell at you. You can use it like a normal variable. Such optional variables will unwrap automatically and you do not need to use any further exclamation mark at the end of the variable to get the assigned value.This way of unwrapping is called implicit unwrapping .But keep in mind that the risk of crashing is high as you will have to manually keep track of the variable usage.
let someString: String! 
print(someString) // risk for crash is high.
We don’t have to use ! to print out the value of someString. Just like forced unwrapping, accessing an implicitly unwrapped optional that is nil will cause the entire program to crash with a runtime error.
Well, we can use our Vehicle class to give an example.
import UIKitclass Vehicle {var model: String!}var cars = Vehicle()print(cars.model) // it may crash the app sometimes. the value is nil.
By using an implicitly unwrapped optional, we are guaranteeing the compiler that we will assign some value to it sometimes in the future.
In most cases, Implicitly Unwrapped Optionals should be avoided because you cannot keep track of all your variables all the time and your entire app will crash when it is accessed while nil. If you are ever not sure about whether a variable can be nil, always default to using a normal Optional. Unwrapping a variable that is never nil certainly doesn’t hurt very much.
Implicit unwrapping is error prone and is not recommended.
Let’s take a simple example −
var myString:String!
myString = "Hello, Swift!"let x = myString // x is an optional string with value "Hello, Swift!"//_______________________________var myOtherString:String!
let x = myOtherString // x will be an optional string. The value is not set (or nil).
let possibleString: String? = "An optional string."let forcedString: String = possibleString! // requires an exclamation mark_______________let assumedString: String! = "An implicitly unwrapped optional string."let implicitString: String = assumedString // no need for an exclamation mark

—Optional Binding :

Use optional binding to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable.
An optional binding for the if statement is as follows −
if let constantName = someOptional {
   //statements using 'constantName' 
} else {
// the value of someOptional is not set (or nil).
}
This is the recommended way of unwrapping an optional.
let possibleNumber = "123" // a string  nonOptional constantif let actualNumber = Int(possibleNumber) {print("\"\(possibleNumber)\" has an integer value of \(actualNumber)")} else {print("\"\(possibleNumber)\" could not be converted to an integer")}// Prints ""123" has an integer value of 123"
This code can be read as:
“If the optional Int returned by Int(possibleNumber) contains a value, set a new constant [or variable] called actualNumber to the value contained in the optional.”
You can include as many optional bindings and Boolean conditions in a single if statement as you need to, separated by commas. If any of the values in the optional bindings are nil or any Boolean condition evaluates to false, the whole if statement’s condition is considered to be false. The following if statements are equivalent:
if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {print("\(firstNumber) < \(secondNumber) < 100")}// Prints "4 < 42 < 100"if let firstNumber = Int("4") {if let secondNumber = Int("42") {if firstNumber < secondNumber && secondNumber < 100 {print("\(firstNumber) < \(secondNumber) < 100")}}}// Prints "4 < 42 < 100"
Constants and variables created with optional binding in an if statement are available only within the body of the if statement. In contrast, the constants and variables created with a guardstatement are available in the lines of code that follow the guard statement.

Digging deeper :

Let’s understand a little more about optionals. Let’s understand how optionals are used inside classes.
Let’s create a class with an optional variable.
//: Playground — noun: a place where people can playimport UIKitclass Vehicle {var model: String?}
Here, the class Vehicle contains an optional variable called model. Now we are going to create a car of type Vehicle.
var car: Vehicle?
This variable car is an optional variable. This means that at some point of time, it may contain a value in it. So, now if we want to get the model of the car, what do we do? Maybe we can do a multi level if-let statement like this:
//: Playground — noun: a place where people can playimport UIKitclass Vehicle {var model: String?}var car: Vehicle?if let c = car {if let m = c.model {print(m)}}
It will work fine. But there is a better way.
if let c = car, let m = c.model {print(m)}
This is a single line if-let statement. First it will check the first statement. If it is valid, then the next statement towards the right will get executed and so on. Now let us see the working code:
//: Playground — noun: a place where people can playimport UIKitclass Vechicle {var model: String?}var car: Vechicle?car = Vechicle() // created a new vehiclecar?.model = “Lamborgini”if let c = car, let m = c.model {
// only execute if car is valid and car has a valid model..print(m)}
IMP: Whenever we are using an optional with a question mark at the end, anytime you are going to use the dot(.) to access the property or something, you’ve got to put a question mark in front of it and say ‘Hey, it’s an optional and I don’t know if there is a value inside or not.
For a better understanding, let us create an array of vehicle which is optional.
import UIKitclass Vehicle {var model: String?}var cars: [Vehicle]?cars = [Vehicle]()cars?.append(Vehicle()) // question mark in front of the dot is because it is an optional variable. if let carArray = cars, carArray.count > 0 {//execute only if cars array is valid and its count is greater than zero.
print(carArray.count)}

Optional chaining :

Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.
SO , while querying the value from an optional, we can use optional chaining and if any value in the chain is nil, the entire chain fails and returns a nil.
let legs = House?.DiningRoom?.Chairs?.Legs?.first 
// just an example.. if chairs is nil, legs will be nil, if house is nil, chairs will obviously be nil and hence the legs..
Consider a class Human with a non - optional variable called age .
import UIKitclass Human {var age: Intinit(age: Int) {self.age = age}}
Consider another class House with an optional variable of type Human .
class House {var human:Human?}
Now we can create an object of House and initialise the age of human with a value.
var houseObj = House()houseObj.human = Human(age: 10)
Now let’s try to access the age of the human in the house.
let ageOfHumanInHouse = houseObj.human?.age //ageOfHumanInHouse is optional Int
Since the type of human is optional, ?gets added automatically. When you access a property whose type is optional, Swift will add ?. Anything that comes after the ? will be optional.
IMPORTANT: Even though age is not an optional variable, since human is optional, the age has to be optional as human may be nil.
Its pretty simple.Lets assume that you saw a dream and you have a luxury house in your dream. The house in the dream is not real and you know that . So everything inside the house like a 100 inch curved LED tv , a lamborghini car in the garage , a luxury bed in the bedroom etc.. everything will be imaginary. It is just pure common sense.
Since ageOfHumanInHouse is optional Int (Int?) , we can use optional binding to unwrap it.
if let ageOfHumanInHouse = ageOfHumanInHouse {print(“\(ageOfHumanInHouse)”)}
Important: Optionals don’t interact with each other. We have to unwrap an optional in order to do that.

What is the nil coalescing operator?

source: Hackingwithswift
Optionals are a powerful source of safety in Swift, but can also be annoying if you find them littered throughout your code. Swift’s nil coalescing operator helps you solve this problem by either unwrapping an optional if it has a value, or providing a default if the optional is empty.
Here’s an example to get you started:
let name: String? = nil
let unwrappedName = name ?? "Anonymous"
Because name is an optional string, we need to unwrap it safely to ensure it has a meaningful value. The nil coalescing operator – ?? – does exactly that, but if it finds the optional has no value then it uses a default instead. In this case, the default is "Anonymous". What this means is that unwrappedName has the data type String rather than String?because it can be guaranteed to have a value.
You don’t need to create a separate variable to use nil coalescing. For example, this works fine too:
let name: String? = nil
print("Hello, \(name ?? "Anonymous")!")
Enjoy!!

Comments

Popular Posts