0

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)
Tiago Marinho
  • 2,146
  • 17
  • 37
Max
  • 5,380
  • 6
  • 42
  • 66
  • Max. Just to clear things, you are not force unwrapping on a nil value. You are force unwrapping on john.residence and it has a value. – BangOperator May 25 '16 at 13:28

2 Answers2

2

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.

Tiago Marinho
  • 2,146
  • 17
  • 37
  • Ok makes sense, but one more question, why would i use john.residence!.numberOfRooms! when i can use john.residence!.numberOfRooms to get my value. – Max May 24 '16 at 07:08
  • When using `.numberOfRooms!` you state that you're totally sure this property will not return `nil`. This is useful for debugging purposes, because if you were expecting a value not to be `nil` and it returns `nil`, your program will quickly stop execution. This will avoid indirect errors caused by values being `nil` where they shouldn't. – Tiago Marinho May 24 '16 at 07:16
  • @Max see my updated answer for more explanation about what's optional chaining. – Tiago Marinho May 24 '16 at 07:29
0

Your app not crash because you have define property numberOfRooms with ?. It means that it will allow null value also.

Use ! instead of ?. It will definitely crash on this statement.

 print(john.residence!.numberOfRooms)

Visit this link it will help you to understand the difference between ? and !.
Difference Between ? and ! in Swift Language?

Community
  • 1
  • 1
Bhumika
  • 876
  • 7
  • 20
  • What you're describing is an _implicitly unwrapped optional_, and the OP problem refers to why his code containing an _optional chain_ doesn't return a runtime error. – Tiago Marinho May 24 '16 at 07:31
  • @Bhumilka john.residence!.numberOfRooms will not crash , please check. it would print a nil value – Max May 24 '16 at 07:35
  • @Max he's saying that if you code the `Residence` initialization as `var numberOfRooms : Int!` (replacing **?** by **!** here) will cause the `print` function to fail. However, do not use this. More on Implicitly Unwrapped Optionals here: http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals – Tiago Marinho May 24 '16 at 07:38