Встречается на 63% собеседований по Mobile

"Weak" и "Unowned" в чем разница

weak и unowned — это два типа слабых ссылок в Swift, которые позволяют избежать утечек памяти при циклических ссылках, но ведут себя по-разному: weak всегда опциональна и автоматически становится nil, когда объект освобождается, а unowned не опциональна и обращение к ней после освобождения объекта вызывает краш. Выбор между ними зависит от времени жизни объектов: weak подходит, когда объект может быть уничтожен раньше, а unowned — когда вы уверены, что объект будет жить столько же или дольше ссылки.

Как это работает

В Swift для управления памятью используется подсчёт ссылок (ARC). Каждая сильная ссылка увеличивает счётчик, и объект не освобождается, пока счётчик не станет нулевым. weak и unowned не увеличивают счётчик, поэтому они не препятствуют освобождению объекта. Это позволяет разорвать циклические ссылки, когда два объекта ссылаются друг на друга.

  • weak — это всегда опциональная ссылка (тип SomeClass?). Когда объект освобождается, ARC автоматически устанавливает её в nil. Это безопасно, потому что вы всегда можете проверить наличие значения перед обращением.
  • unowned — это неопциональная ссылка (тип SomeClass). Она не обнуляется при освобождении объекта. Если вы обратитесь к ней после освобождения, программа упадёт с ошибкой времени выполнения.

Пример

Рассмотрим классический пример с двумя классами, которые ссылаются друг на друга.

swift
class Person {
    var apartment: Apartment?
}

class Apartment {
    weak var tenant: Person?  // слабая ссылка, чтобы избежать цикла
}

Здесь Apartment имеет слабую ссылку на Person. Если Person освободится, tenant станет nil. Это безопасно, потому что квартира может существовать без жильца.

Теперь пример с unowned:

swift
class Customer {
    var creditCard: CreditCard?
}

class CreditCard {
    unowned let customer: Customer  // несильная ссылка, гарантированно существует
}

Здесь CreditCard всегда принадлежит конкретному Customer, и время их жизни совпадает. Поэтому unowned безопасно: кредитная карта не может существовать без владельца, и владелец не будет освобождён раньше карты.

Подводные камни

  • Обращение к unowned после освобождения — приводит к крашу. Это главный риск. Используйте unowned только если вы абсолютно уверены в порядке жизни объектов.
  • weak всегда опциональна — это значит, что вам нужно разворачивать её (например, через guard let или if let). Это добавляет немного кода, но повышает безопасность.
  • Циклические ссылки в замыканиях — часто используют [weak self] или [unowned self] в списке захвата. Здесь действуют те же правила: weak безопаснее, unowned — если замыкание не переживёт объект.
  • Производительностьweak имеет небольшие накладные расходы из-за опциональности и обнуления, но в большинстве случаев это не критично.

Когда использовать

  • Используйте weak, когда объект может быть освобождён раньше, чем ссылка, и вы хотите избежать висячих указателей. Это стандартный выбор для делегатов, обратных ссылок и замыканий.
  • Используйте unowned, когда вы точно знаете, что объект будет жить столько же или дольше, чем ссылка. Например, когда один объект является владельцем другого, и время их жизни совпадает.

Коротко

  • weak — опциональная ссылка, автоматически становится nil при освобождении объекта.
  • unowned — неопциональная ссылка, не обнуляется, обращение после освобождения вызывает краш.
  • Выбирайте weak для безопасности, unowned — когда гарантирован порядок жизни.
  • В замыканиях используйте [weak self] или [unowned self] для предотвращения циклов.
как отвечать на вопрос
пример собеседования
фреймворки на собеседовании
типичные вопросы junior
интервью вопросы и ответы