Do you think IIT Guwahati certified course can help you in your career?
No
Introduction
You might have used optionals in swift many times till now. Optionals are a type of container with only two possibilities: either it can contain a value or null. Now, how do we handle the optionals? That is what we are going to discuss in this article.
In this article, we will discuss Swift Optional Chaining and what is the need for swift optional chaining. We will also discuss if swift optional chaining is better than forced unwrapping and why. Then we will see how forced unwrapping creates runtime errors which, in the case of swift optional chaining, it is handled gracefully. We will also see different scenarios where we can use swift optional chaining, and we will explain everything with examples for your better understanding.
Swift Optional Chaining
The technique of querying and calling properties, methods, and subscripts on an optional is known as optional chaining.
Now, what is an Optional 🤔? As evident by its name, it will give you options. By using an optional, you can use one thing or the other. It's similar to an MCQ question where you have two options, either this or that.
We get the Optional part, but why Chaining 🤔? It is called Chaining because multiple queries can be chained together to form a nested if-else-like structure.
The entire chain fails if any of these properties, methods, or subscripts are nil when accessed. There are only two possibilities for each of them, and that is either there is a value, or it is nil.
Now, you can argue why we would use Swift Optional Chaining if we already have forced unwrapping. We have discussed this below.
Optional Chaining in Place of Forced Unwrapping
We will understand the difference between forced unwrapping and optional chaining using an example.
Let's suppose there is a property of a class that you want it to be optional. For example, there is a laptop class that contains a property named specification which stores the details of that laptop. Let's say you don't have the details of a laptop; then the specification property can be optional, as shown below.
class Laptop {
/* Adding (?) sign after details
because this is optional property */
var specification : details?
}
class details {
var brand = "HP"
var RAM = "16 GB"
}
When we create an instance of the Laptop class, the specification property will be nil. So, let's try to access this by using both methods: forced unwrapping and optional chaining.
Forced unwrapping is done using a (!) sign after the optional property, as shown below.
Code
class Laptop {
var specification : details?
}
class details {
var brand = "HP"
var RAM = "16 GB"
}
// Creating instance of Laptop
let device = Laptop()
// Forced unwrapping
let memory = device.specification!.RAM
Output
The above code produces a runtime error because the property we are trying to access is nil.
Now, let's do this using Swift Optional Chaining. In optional chaining, if the optional contains a value, the remaining code in the chain is executed, but if it is nil, then the chain is broken, and else part of the code is executed. It is implemented in the code given below.
Code
class Laptop {
var specification : details?
}
class details {
var brand = "HP"
var RAM = "16 GB"
}
// Creating instance of Laptop
let device = Laptop()
// Optional Chaining
if let memory = device.specification?.RAM {
print("Laptop has \(memory) RAM memory.")
}
else {
print("RAM details not available for this laptop")
}
Output
Since the accessed property was nil, it executed the else part of the code and returned this output.
Now, let's assign the 'details' instance to 'device.specification' so that it no longer contains a nil value. If we try to access the specification property, it will go in the if condition. You can refer to the code below to check for yourself.
Code
class Laptop {
var specification : details?
}
class details {
var brand = "HP"
var RAM = "16 GB"
}
// Creating instance of Laptop
let device = Laptop()
device.specification = details()
// Optional Chaining
if let memory = device.specification?.RAM {
print("Laptop has \(memory) RAM memory.")
}
else {
print("RAM details not available for this laptop")
}
Output
Model Classes for Optional Chaining
Swift Optional chaining can be used with properties, methods, and subscripts having multiple levels. This will allow us to go deep into the levels and check whether it's possible to access them.
Let us build a complex class structure which we will then use as an example to understand how optional chaining works with properties, methods, and subscripts. The code for the classes is given below. The explanation for the construction of these classes is given below the code.
Code
// Model class 1
class Libraries {
var library : Library?
}
// Model class 2
class Library {
var books: [Book] = []
var numberOfBooks: Int {
return books.count
}
subscript (i: Int) -> Book {
get {
return books[i]
}
set {
return books[i] = newValue
}
}
func printNumberOfBooks() {
print("The number of books is \(numberOfBooks)")
}
var location : Location?
}
// Model class 3
class Book {
let name: String
init(name: String) { self.name = name }
}
// Model class 4
class Location {
var Area : String?
var StreetName : String?
}
// Initializing college class
let library1 = Libraries()
if let bookCount = library1.library?.numberOfBooks {
print("Library has \(bookCount) number of books")
}
else {
print("Book information of this library is not available")
}
Output
We get this output because library1.library is nil. So, it will go in the else condition, and print Book information of this library is not available.
Code Explanation
Model class 1
class Libraries {
var library : Library?
}
The Libraries class has an optional library property.
Model Class 2
class Library {
var books: [Book] = []
var numberOfBooks: Int {
return books.count
}
subscript (i: Int) -> Book {
get {
return books[i]
}
set {
return books[i] = newValue
}
}
func printNumberOfBooks() {
print("The number of books is \(numberOfBooks)")
}
var location : Location?
}
The 'Library' class defines a variable property, namely 'books,' which is initialized with an array of type '[Book].'
numberOfBooks property returns the value of the 'count' property showing the count of the books array. It is implemented as a computed property, not a stored property.
Subscript provides read-write access to the book at the desired index in the books array.
printNumberOfBooks is a method that simply prints the number of books in the 'library.'
It defines a 'location' property which is optional with a type of 'Location?'.
Model Class 3
class Book {
let name: String
init(name: String) { self.name = name }
}
The Book class is a simple class with one property called name and an initializer to set that property to a suitable book name. It is used in the 'books' array.
Model Class 4
class Location {
var Area : String?
var StreetName : String?
}
Location class has two optional properties of type String? to identify the location.
Now, we will use these model classes to understand further concepts.
Use of Optional Chaining
Optional chaining can be used with properties, methods, and subscripts in the below-given ways.
Accessing properties through Optional Chaining
Calling methods through Optional Chaining
Accessing subscripts through Optional Chaining
Access Properties Through Optional Chaining
This is similar to what we did in our first demonstration, where we tried to access a nil property. For the above code, if we create an instance of the 'Libraries' class and then try to access the 'numberOfBooks' property using optional chaining, then we will go to the else condition because that property is nil.
You can add the code given below to the previous code and see the new output. The output shows that the else condition is visited and the 'if' condition is not visited due to the reason mentioned above.
Code
let library2 = Libraries()
if let bookCount = library2.library?.numberOfBooks {
print("This Library has \(bookCount) books.")
} else {
print("No info on number of books")
}
Output
Suppose we try to assign a new location to the location property of the library of library2. In that case, it won't work because the '=' operator comes after the optional chaining '?' operator. Hence, the assignment is also part of optional chaining, and since its property is nil, it won't see the code after the '?' operator.
Similar to accessing properties, optional chaining can be used to call methods and check whether that method call is successful.
For example, in the above code, if we try to access the printNumberOfBooks() method through optional chaining, it will send us to the else part because the department property of the 'library2' instance of the 'Library' class is still nil.
Note: functions and methods having no return type have an implicit return type of 'Void?'
You can refer to the code given below to relate to this.
Code
if library2.library?.printNumberOfBooks() != nil {
print("Info on number of books is available")
} else {
print("Info on number of books is not available")
}
Output
Access Subscripts through Optional Chaining
We can use the optional chaining technique to try to get and set a value from a subscript on an optional value and then check whether that subscript call is successful.
In our example code, add the code given below.
Code
if let NameOfFirstRoom = college2.department?[0].name {
print("The first room name is \(NameOfFirstRoom).")
} else {
print("Not able to get room name")
}
Here, we are trying to access the name property of the first room in the 'rooms' array using subscripts with optional chaining. Since college2.department is nil, therefore we will go to the else part. So, the output will be from the else part.
Output
Similarly, if we try to assign a 'Book' to 'library2.library', then also we won't be able to do that because of the same reason.
This also fails because library2.department is nil. Check out this problem - Longest String Chain
Frequently Asked Questions
What is Optional Chaining in swift?
The technique of querying and calling properties, methods, and subscripts on an optional is known as optional chaining.
What is Forced Unwrapping in swift?
It is the action of extracting the value contained inside an Optional.
What are Optionals?
Optional is a type of container which may or may not contain a value.
Where do we use Optional Chaining?
Optional chaining can be used to access properties, calling methods, and accessing subscripts.
What is the return type of a function that doesn't return anything?
Functions and methods having no return type have an implicit return type of 'Void?'
Conclusion
This article taught us about Swift Optional Chaining and what is the need for optional chaining. We also discussed how optional chaining counters the run time error problem of forced unwrapping and the use cases of optional chaining. We hope this blog has helped you enhance your iOS and swift knowledge. Here is a list of articles that can help you learn more about ios development and swift.