Опциональна последовательность, разница в присвоении


#1

Кто может обьяснить в чем разница с присванием для опциональной последовательности. Результат один и тот же.

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { print("\(name) освобождается") }
    }

    class Apartment {
    let unit: String
    init(unit: String) { self.unit = unit }
    var tenant: Person?
    deinit { print("Апартаменты \(unit) освобождаются") }
    }

    var john: Person?
    var unit4A: Apartment?

    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")

    john?.apartment = unit4A
    dump(john)

    john!.apartment = unit4A
    dump(john)

#2

Не вижу никакой разницы. И должна ли она быть?
С чего возник такой вопрос?


#3

В первом случае john? означает, что john может быть nil и тогда последовательность вернёт nil.
Во втором john! соответственно идёт принудительное извлечение опционала john: это значит, что там всегда должно быть значение и если там будет nil, то всё упадёт.

Опциональные цепочки


#4

При чтении Автоматический подсчет ссылок (ARC) есть абзац

Теперь вы можете соединить эти два экземпляра вместе, так что житель будет иметь апартаменты, а апартаменты будут иметь своих жителей. Обратите внимание, что восклицательный знак (!) используется для развертывания и допуска к экземплярам,
john!.apartment = unit4A
unit4A!.tenant = john

Я и задумался, а какой смысл так делать, если можно через опциональную последовательность в данном случае присвоить. Решил уточнить, может я чего-то не понимаю.


#5

Обычно ! в цепочке используется, когда вы точно уверены, что опциональный элемент в цепочке не nil: например, когда вы ранее уже проверили соотвествующий объект (переменную john) на nil

if john != nil {
    john!.apartment = unit4A
}

Поскольку john - это опционал, то в любом случае доступ к его свойствам будет через опциональную цепочку. Вид цепочки (? или !) будет зависит только от вашей логики. Естествеено нельзя принудительно разварачивать в цепочке если вы до этого не проверили на nil.