Updated 31 August 2019
Optional Chaining in swift is the process in which we can query or call the methods, properties or subscripts of an optional that might be nil. Generally, in swift optional chaining will return a value in two ways.
value.nil, then calling the property, method or subscription of an optional will return nil.In swift, multiple queries can be chained together due to that if any link in the chain fails or return a nil value, the entire chain will fail and return a nil value.
You specify optional chaining by placing a question mark (?) after the optional value on which you wish to call a property, method or subscript if the optional is not-nil. This is very similar to placing an exclamation mark (!) after an optional value to force the unwrapping of its value. The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.
The result of optional chaining will be of the same type as expected return value with wrapped in an optional. A property that normally returns an String will return a String?when accessed through optional chaining.
The below code snippets demonstrate how optional chaining differs from forced unwrapping and enables you to check for success.
First, two classes called Company and Address are defined:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Company { var address: Address? } class Address { var street: String var postcode: String var city: String var country: String init(street: String, postcode: String, city: String, country: String) { self.street = street self.postcode = postcode self.city = city self.country = country } } |
Address instances have the optional property like street, postcode, city, country. Company instances have an optional address property of type Address?.
If you create a new Company instance, its address property is default initialized to nil, by virtue of being optional. In the code below, webkul has a address property value of nil:
|
1 |
let webkul = Company() |
If you try to access the country property or any other property of this company’s address, by placing an exclamation mark after address to force the unwrapping of its value, you trigger a runtime error, because there is no address value to unwrap:
|
1 2 |
let country = webkul.address!.country // this triggers a runtime error |
The code above succeeds when webkul.address has a non-nil value and will set country to an String value containing the appropriate country. However, this code always triggers a runtime error when address is nil, as illustrated above.
Optional chaining provides an alternative way to access the value of country. To use optional chaining, use a question mark in place of the exclamation mark:
|
1 2 3 4 5 6 |
if let country = webkul.address?.country { print("Webkul's head office is in \(country).") } else { print("Unable to retrieve the country.") } // Prints "Unable to retrieve the country." |
This tells Swift to “chain” on the optional address property and to retrieve the value of country if address exists.
Because of the attempt to access the potential to fail, the optional chaining returns a value of type String?, or “optional String”. When address is nil, as in the example above, this optional String will also be nil, to reflect the fact that it was not possible to access country. The optional String is accessed through optional binding to unwrap the string and assign the non-optional value to the country variable.
Note that this is true even though country is a non-optional String. The fact that it is queried through an optional chain means that the call to country will always return an String? instead of an String.
You can assign a address instance to webkul.address, so that it no longer has a nilvalue:
|
1 |
webkul.address = Address(street: "Sector 63", postcode: "201301", city: "Noida", country: "Indeia") |
webkul.address now contains an actual Address instance, rather than nil. If you try to access country with the same optional chaining as before, it will now return an String?that contains the country value as India:
|
1 2 3 4 5 6 |
if let country = webkul.address?.country { print("Webkul's head office is in \(country).") } else { print("Unable to retrieve the country.") } // Prints "Webkul's head office is in India." |
If you have more details or questions, you can reply to the received confirmation email.
Back to Home
Be the first to comment.