
There's more...
So far, we have seen non-optional variables, where a value of the correct type must be provided, and optional variables, where the value can either be the underlying type or nil. In a perfect world, this would be all we need. However, we may often find ourselves in the situation where we need to define a variable that we know should have a non-nil value, and, when it comes to be used, will have a value, but at the point of declaration, we don't know exactly what that value is. For these situations, we can declare a variable as an implicitly unwrapped optional (IUO) in Swift.
Run the following code in the playground:
var legalName: String!
// At birth
legalName = nil
// At birth registration
legalName = "Alissa Jones"
// At enrolling in school
print(legalName)
// At enrolling in college
print(legalName)
// Registering Marriage
legalName = "Alissa Moon"
// When meeting new people
print(legalName)
In this example, we have a person's legal name, which is used at many points during their life, for instance, when registering for educational institutions. It can be changed, either by legal request or through marriage, and yet you would never expect someone's legal name to not exist. However, that is exactly what happens when someone is born! When a person is born (or initialized!), they don't have a legal name until their birth is registered. So, if we were trying to model this in code, a person's legal name could be represented as an IUO.
In code, we declare a variable to be an IUO by placing a ! sign after the type:
let legalName: String!
There is some subtlety to how IUOs behave when they are assigned to other variables and the type is inferred. Put the following into the playground, as it's best illustrated with code:
var input: Int! = 5 // Int!
print(input) // 5
var output1 = input // Int?
print(output1 as Any) // Optional(5)
var output2 = input + 1 // Int
print(output2) // 5
When an IUO is assigned to a new variable, the compiler can't be sure that there is a non-nil value assigned. So, if an IUO is assigned to a new variable, as is the case with output1 here, the compiler plays it safe and infers that the type of this new variable is an optional. If, however, the value of the IUO has been unwrapped, then the compiler knows that it has a non-nil value, and will infer a non-optional type. When assigning output2 earlier, the value of the input is unwrapped in order to add 1 to it; therefore, the type of output2 is inferred to be the non-optional Int.