Search code examples
xcodeswiftoption-typeforced-unwrappingoptional-chaining

Printing without force-unwrapping property doesn't trigger runtime error in Swift


I have the below code and it works fine, but I was expecting the line print(john.residence!.numberOfRooms) to crash, as my numberOfRooms variable has nil value and I am not using forced wrapping when passing its value as argument to print(). Can anyone please explain why is this not triggering a runtime error and printing nil safely instead?

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms: Int?
}

let john = Person()

john.residence = Residence()

print(john.residence!.numberOfRooms)

Solution

  • What you are doing is called Optional Chaining. Both Optional Chaining and Forced Unwrapping do the same thing, but:

    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 Swift Programming Language (Swift 2.2).” iBooks. https://itun.es/br/jEUH0.l

    You're force unwrapping the .residence property, which is not nil: It contains a Residence instance, which has its .numberOfRooms property set as nil because it wasn't initialized. Since you're not force unwrapping it, no errors are given, due to optional chaining. Try force unwrapping the .numberOfRooms property instead to get an error:

    print(john.residence!.numberOfRooms!)
    

    Or, you can remove the following line to set .residence as nil:

    john.residence = Residence()
    

    This way john has no .residence, so trying to force unwrap it will make the Swift compiler throw a runtime error.