[Swift] Optional
Answering Interview Questions Related to Optional
- What is Optional?
- Explain how Optional is implemented in Swift.
- How can we unwrap Optional to use its value?
- Explain Optional Binding using guard statement.
- What is Optional Chaining?
The Basics of Optional
public enum Optional<Wrapped>: ExpressibleByNilLiteral {
case none
case some(Wrapped)
}
One of the ways Swift guarantees its safety is by Optional. Optional is used when there may or may not be a value in a variable or a constant.
Optional is defined using enumeration in Swift that has 2 cases. Case ‘none’ to indicate that there is no value and ‘some’ to suggest an existence of a value although it’s wrapped. Thus, it must be unwrapped if you want to make use out of it. Swift provides us with 3 methods thus it’s your choice to choose which to adopt.
< A bit more about Optional😀 >
‘nil’ in Swift is different from that of Objective-C’s. Objective-C can return nil pointers in a function when there is no valid object. However, Optional in Swift can be applied to all types, making the language more expressive than Objective-C.
Unwrapping Optional
Forced Unwrapping (Unconditional Unwrapping)
Forced unwrapping is used when you can ensure there’s a value in an Optional. However, when your attempt of force unwrapping returns ‘nil’, a runtime error occurs. When such happens, you’ll likely see a runtime error message saying Fatal error: Unexpectedly found nil while unwrapping an Optional value
.
Forced unwrapping can be done using an exclamation mark(!).
let a: Int? // nil is automatically assigned
print(a!) // runtime error
Optional Binding
Optional binding is used to check whether a value exists using the ‘if’ or ‘while’ statement. If a wrapped value exists, it enables you to extract the value, assign it to a variable/constant that can be used inside the statement’s scope.
var myAddress: String = "Seoul, Korea"if let address = myAddress {
print("Sue lives in \(address)")
}
Optional binding can also be done using guard-statement. When if-statement is used, the constant that stores the unwrapped value can only be used inside the statement scope whereas the constant created by guard-statement allows you to use it like a local variable. However guard-statement must always have an else clause to either call a function with the Never
return type or transfer program control outside the guard statement’s enclosing scope. So guard-statements come in handy when there’s a need for exception handling.
Implicitly Unwrapped Optional
If you can assure that there will always be a value in an Optional whenever you use it, then it would be frustrating if you have to unwrap value using optional binding. That’s when implicitly unwrapped optional is useful. All you need to do is to put an exclamation mark(!) at the end of a type instead of a question mark(?).
It can be used in several situations like creating IBOutlets using storyboard or when initializing class to avoid retain cycles. (Example)
class Country {
let name: String
var capitalCity: City!
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
Optional Chaining
Optional chaining is used to call or retrieve a value from properties, methods or subscripts. It’s done by chaining multiple optional values. Accessing via optional chaining returns an optional so you must also choose one of the unwrapping methods if you want to manipulate the value.
let person: Person = Person(name: "Sueaty")
if let roomNumber: Int = person.address?.room?.number {
print("Sueaty stays in room: #\(roomNumber)")
} else {
print("Cannot find room number")
}