Когда оба свойства никогда не могут быть равны нулю, какая разница между несобственными и распределенными ресурсами?

Для следующего кода из руководства по быстрому программированию с добавленными мной деинициализаторами итоговая распечатка отладки будет одинаковой независимо от того, используется ключевое слово unowned или нет. В быстром руководстве по программированию говорится, что использование неизвестных и неявно развернутых опций является способом разрыва циклов сильной ссылки, когда оба свойства, которые ссылаются на экземпляры классов друг друга, никогда не будут равны нулю. Если оба свойства никогда не будут равны нулю, чем это отличается от сильного эталонного цикла? Например, почему мы пытаемся использовать ключевое слово unowned в этом конкретном случае, особенно когда показания отладки показывают, что распределение памяти не отличается от того, используется unowned или нет?

class Country {
    let name: String
    var capitalCity: City!
    init(name: String, capitalName: String) {
        self.name = name
        self.capitalCity = City(name: capitalName, country: self)
    }
    deinit {print("\(name) is being deinitialized")}
}

class City {
    let name: String
    unowned let country: Country
    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
    deinit {print("\(name) is being deinitialized")}
}

var canada = Country(name: "Canada", capitalName: "Ottawa")
print("\(canada.name)'s capital city is called \(canada.capitalCity.name)")
canada.capitalCity = City(name: "Vancouver", country: canada)

Отладочная информация:

Canada's capital city is called Ottawa
Ottawa is being deinitialized

Примечание: это было на детской площадке.

1 ответ

Решение

Вы, очевидно, смотрите на это на игровой площадке или в какой-то среде, где вы не позволяете им выпадать из области видимости (например, если они являются свойствами какого-либо объекта, посмотрите, что происходит, когда этот объект сам по себе освобождается). Но для наглядности рассмотрим следующую перестановку вашего кода:

func foo() {
    let canada = Country(name: "Canada", capitalName: "Ottawa")
    print("\(canada.name)'s capital city is called \(canada.capitalCity.name)")
    canada.capitalCity = City(name: "Vancouver", country: canada)
}

foo()

Это как ваш пример, но я ограничиваю область действия этих переменных в пределах foo функция, так что я должен быть в состоянии увидеть полный жизненный цикл объектов, созданных и уничтоженных в этой области.

С unowned ссылка на Country в City он сообщит:

Столица Канады называется Оттава
Оттава деинициализируется
Канада деинициализируется
Ванкувер деинициализируется

И без unowned (и не weakЛибо), он сообщит:

Столица Канады называется Оттава
Оттава деинициализируется

Обратите внимание на отсутствие каких-либо печатных заявлений, связанных с деинициализацией "Канада" или "Ванкувер". Это потому, что в отсутствие unowned ссылка, вы в конечном итоге получаете сильный цикл ссылок между "Канадой" и "Ванкувером", и они не деинициализированы.

Таким образом, тот факт, что вы видите де-инициализацию "Оттавы", не имеет ничего общего с сильным циклом ссылок. Это просто деинициализируется, потому что "Оттава" была заменена на "Ванкувер", оставляя "Оттаву" без более сильных ссылок, и она деинициализирована.

И вы не должны делать никаких выводов об отсутствии каких-либо доказательств вашего print заявления в вашем deinit в вашем оригинальном примере. Вы могли бы сделать это на игровой площадке, или они могли быть свойствами какого-то объекта, который сам по себе еще не был освобожден. Помещение этих переменных в ограниченную область, как я сделал с foo Функция выше лучше иллюстрирует истинный жизненный цикл этих объектов, когда они выпадают из области видимости. И это показывает нам результат не решения наших сильных эталонных циклов.

Итог, вам нужно unowned (или же weak) ссылка на Country в City сломать этот сильный референсный цикл. Вопрос не только в том, могут ли эти переменные быть установлены nilно также возможно ли для них когда-либо выпасть из области видимости и быть деинициализированными.

Другие вопросы по тегам