Будет ли объект в Swift (ARC) освобожден, если на него указывает одна сильная (strong), три слабых (weak) и одна бесхозная (unowned) ссылка?

Ответ

Да, объект будет немедленно освобожден (деинициализирован) при обнулении последней сильной ссылки. Слабые (weak) и бесхозные (unowned) ссылки не увеличивают счетчик ссылок (retain count), поэтому не влияют на время жизни объекта.

Механика:

class Example { deinit { print("Объект освобожден") } }

var strongRef: Example? = Example() // Retain count = 1
weak var weakRef1 = strongRef       // Retain count = 1
weak var weakRef2 = strongRef       // Retain count = 1
weak var weakRef3 = strongRef       // Retain count = 1
unowned var unownedRef = strongRef! // Retain count = 1

strongRef = nil // Retain count становится 0 -> объект освобождается.
// Консоль: "Объект освобожден"

// Последствия:
print(weakRef1)     // nil
print(weakRef2)     // nil
print(weakRef3)     // nil
// print(unownedRef) // КРАШ! Попытка доступа к освобожденному объекту через unowned.

Ключевые различия ссылок:

  • strong: Удерживает объект живым. Увеличивает retain count.
  • weak: Не удерживает объект. Автоматически становится nil после освобождения объекта. Безопасна.
  • unowned: Не удерживает объект. Не становится nil. Предполагает, что объект проживет дольше ссылки. Опасна при неправильном использовании (краш).

Вывод: Для освобождения памяти важен только счетчик сильных ссылок.

Ответ 18+ 🔞

А, ну ты про это, про ссылки эти ваши, блядь, в свифте! Да, конечно, ёпта, объект-то нахуй полетит в деинит, как только последнюю сильную ссылку отпустишь. Это ж как последний патрон в обойме, блядь — щёлк, и всё, пиздец.

Слабые да бесхозные — это так, мартышлюшки, блядь. Они на счётчик-то, на retain count, нихуя не влияют. Сидит он, объект, держится из последних сил, а эти вокруг него пляшут: «ой, мы слабенькие, мы не считаемся». Ну и хуй с ними.

Вот смотри, как это выглядит, на примере, чтоб понятно было, куда ветер дует:

class Example { deinit { print("Объект освобожден") } }

var strongRef: Example? = Example() // Retain count = 1
weak var weakRef1 = strongRef       // Retain count = 1
weak var weakRef2 = strongRef       // Retain count = 1
weak var weakRef3 = strongRef       // Retain count = 1
unowned var unownedRef = strongRef! // Retain count = 1

strongRef = nil // Retain count становится 0 -> объект освобождается.
// Консоль: "Объект освобожден"

// Последствия:
print(weakRef1)     // nil
print(weakRef2)     // nil
print(weakRef3)     // nil
// print(unownedRef) // КРАШ! Попытка доступа к освобожденному объекту через unowned.

Видишь? Обнулил strongRef — и всё, приехали. Слабые ссылки сразу в nil превратились, как честные ребята. А вот эта хитрая жопа, unowned, она же не становится nil, она как была, так и осталась указывать в ту же дыру, где объект раньше жил. И если туда полезешь — оп-па, краш, в рот меня чих-пых! Прямо в лоб получаешь.

Короче, запомни раз и нахуй:

  • strong — это главный держатель, мужик с яйцами. Пока он есть, объект живёт.
  • weak — это такой подхалим, блядь. Объект жив — он тут как тут. Объект сдох — он сразу «ой, а я ни при чём, я nil».
  • unowned — это, блядь, максималист, как тот Герасим из рассказа. Либо объект живёт дольше, чем эта ссылка (и тогда всё ок), либо ты получаешь краш и сидишь потом, думаешь: «Что же я, мудак, сделал?».

Так что вся магия, вся эта ебаная механика освобождения памяти, крутится только вокруг сильных ссылок. Остальное — просто декорации, чтобы мозг выебать.