Everyone who has been working with swift knows the concept of optionals. An optional represents two possibilities: Either there is a value, and by unwrapping the optional you can access that value, or there isn’t a value at all. Forced unwrapping can be used by placing an exclamation mark (!) after an optional value to force the unwrapping of its value. But the problem with forced unwrapping is, it triggers the runtime error if the optional is nil. So what if we don’t want this runtime error, Is there any alternative which fails gracefully without giving runtime error? Answer is yes! there is such alternative which is commonly known as optional chaining.
In this introduction about optional chaining, I am going to make you familiar with multiple uses of optional chaining. So what are we waiting for? Let’s get started right away.
What is optional chaining?
Before we get to know about uses of optional chaining, let me first tell you what optional chaining is. Optional chaining is a process for querying and calling properties,methods and subscripts on an optional that might currently be nil. As we know that optional represents two probabilities i.e there is a value or there isn’t value at all. This is why when the property, method or subscript calls on optional and the optional contains a value, then the call succeeds; if the optional is nil, the property, method or subscript call returns nil. It is called chaining because multiple queries can be chained together and if any link in this chain is nil then the entire chain fails gracefully.
How optional chaining is different the forced unwrapping
We know that we use exclamation mark (!) after an optional value to force the unwrapping of its value. Similarly question mark(?) is placed after an optional on which you wish to call a property, method or subscript if the optional is non-nil. Even if the property, method, or subscript which is queried returns a non-optional value, the result of optional chaining is always an optional value to reflect the fact that optional chaining can be called on a nil value. For example, a method that normally returns a String will return a String? when called through optional chaining. To understand the difference between optional chaining and forced unwrapping, let me explain with following code snippets.
First let’s define two classes called Student and Course
Now, if you create a new Student instance ,its degree property is by default initialized to nil because it is optional . So in the code below, nidhi has a degree property value of nil.
In this case, if you try to access the courseTitle property of this Student’s degree by placing exclamation mark after degree, i.e if you try to force unwrap its value, it will trigger a runtime error as there is no degree value to unwrap. Now let’s see how optional chaining works differently with following example.
With optional chaining, if the optional contains a value, the remaining code in the chain is executed, if it is nil then the chain is broken and else part of code is executed. Note that though courseTitle is a non-optional String, as it is queried through an optional chain means that the call to courseTitle will always return a String? instead of a String. So now let’s assign Course instance to nidhi.degree so that it no longer contains nil value.
nidhi.degree = courseTitle()
Now if you try to access the courseTitle with above optional chaining, it will now return string? which contains default courseTitle value of “B.Tech” . So output will be “Nidhi is persuing B.Tech.”
Swift Model Classes for Optional Chaining
One of the important uses of optional chaining is that it allows us to declare an optional in complex classes where we can call any variable or constant properties,methods etc. This flexibility let us drill down into subproperties within complex models of interrelated types, and also it enable us to check if we can access properties, methods, and subscripts on those subproperties. Let’s understand this better with following example. In this example we will declare two classes, out of which one class is complex class (College) and another one (Student) is to access its optional value.
Here class College stores an array of ClassRoom instances, its noOfClasses property is implemented as a computed property. The computed property noOfClasses simply returns the value of the count property from the classes array. As a shortcut to accessing its classes array, this class College provides a read-write subscript that provides access to the class room at the requested index in the classes array. Class College also provides a method called printNoOfClasses, which simply prints the number of class rooms in the college. Finally, College defines an optional property called address, with a type of Address class. The ClassRoom class used for the classes array is a simple class with one property called className, and an initializer to set that property to a suitable class room name.
When we run above code on playground, we will get a result , “Unable to Retrieve No. of Classes” because john.clg is nil.
Accessing Properties Through Optional Chaining
Optional chaining can be used to access a property on an optional value. We also get to know if that property access is successful because of optional chaining. As we have seen in above example, when we try to access the the noOfClasses, the chaining fails because the john.clg is nil. Now let’s see what happens if we try to set a property’s value through optional chaining with following example.
In this example, the attempt to set the address property of john.clg will fail, because john.clg is currently nil.
Calling Methods Through Optional Chaining
We can use optional chaining to call a method on an optional value as well as to check if that method call is successful. This is possible even if the method doesn’t return any value. The method which doesn’t return any value returns void, i.e it returns a value of (), or an empty tuple. If you call such method on optional chaining, it will return void? because the result of optional chaining is always optional. For example, we can use if statement to check if it’s possible to call the printNoOfClasses() method even when the method doesn’t define any return value. As we know that this method call through optional chaining will return optional value if successful, we can compare the return value from printNoOfClasses() call against nil to know if the method call is successful or not. Let’s see the code snippet which demonstrate this.
Accessing Subscripts Through Optional Chaining
Along with calling methods and accessing properties, optional chaining can also be used to try to retrieve and set a value from a subscript on an optional value, and to check whether that subscript call is successful. This can be explained in better manner with following example.
john.clg is currently nil so the subscript call fails.
Even if we try to set a new value through a subscript with optional chaining like
john.clg? = Room(name: “Classroom-1”)
As clg is currently nil, this subscript setting attempt also fails .
We can use optional chaining to access the actual items in the classes array if we create and assign an actual College instance to john.clg, with one or more ClassRoom instances in its classes array.
Accessing Subscripts of Optional Type
If a subscript returns a value which is optional, for example, key subscript of dictionary type in Swift, the values of array or dictionaries which is declared with an optional type can be modified. To chain subscript on its optional return value, place a question mark after the subscript’s closing bracket. To understand this, take a look at following code snippet.
Linking Multiple Levels of Chaining
One interesting fact about linking multiple levels of optional chaining is, we can add many levels to drill down to properties, methods or subscripts but multiple levels of optional chaining do not add more levels of optionality to the returned value.
Now you know multiple uses of optional chaining in swift. So why don’t you open playground and start playing with it to get good commend on it?