iloveios
iloveios

Reputation: 37

Swift Optional chaining

This code is from Apple's new book. My question is: How come "let roomCount = john.residence?.numberOfRooms" is nil, I thought .numberOfRooms should be 1 but in xcode it says is nil I just don't get why is nil. If anyone can clarify me this that would be awesome. Thank you in advance.

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
}

let john = Person()

let roomCount = john.residence?.numberOfRooms

john.residence = Residence()

john.residence?.numberOfRooms


if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}

Upvotes: 0

Views: 1411

Answers (3)

KTPatel
KTPatel

Reputation: 1310

In the example, line let john = Person() creates a object john of type Person.

Person type consist of optional property residence i.e. var residence: Residence?

Here residence is nil because Type Residence is not initialized yet. But one can access its property numberOfRooms even residence is nil (because here Optional Chaining is used) and result of accessing it, is nil

let roomCount = john.residence?.numberOfRooms

Afterward when residence is initialized and assigned,

john.residence = Residence()

Now, john.residence object is initialized and when accessing its numberOfRooms property, it returns default assigned value 1.

In swift, properties are accessible for optional types whether they are nil or not (initialized or not initialized).

Optional Chaining

Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.

Find reference here

Upvotes: 2

Jason Nam
Jason Nam

Reputation: 2011

let roomCount = john.residence?.numberOfRooms

in this line the roomCount have to be nil because you didn't set the residence instance variable. roomCount is not nil when it comes after john.residence = Residance().

Okey so

let roomCount = john.residence?.numberOfRooms

is like this

let roomCount: Int! = nil

if let unwrappedResidence = john.residence
{
    roomCount = unwrappedResidence.numberOfRooms
}

So If residence is nil, the roomCount is being nil.

Upvotes: 3

Dharmesh Kheni
Dharmesh Kheni

Reputation: 71852

residence is not initialised yet when you are trying to use it with:

let roomCount = john.residence?.numberOfRooms

So this will always print nil because residence have nothing to return.

If you want to use .numberOfRooms first initialise your residence instance and use it this way:

let john = Person()
john.residence = Residence()
let roomCount = john.residence?.numberOfRooms  // 1

One more way to do it is initialise it into your Person class:

class Person {
    var residence = Residence()
}

Now you can use .numberOfRooms this way:

let john = Person()
let roomCount = john.residence.numberOfRooms  // 1

Upvotes: 2

Related Questions