"Weak" и "Unowned" в чем разница
weak и unowned — это два типа слабых ссылок в Swift, которые позволяют избежать утечек памяти при циклических ссылках, но ведут себя по-разному: weak всегда опциональна и автоматически становится nil, когда объект освобождается, а unowned не опциональна и обращение к ней после освобождения объекта вызывает краш. Выбор между ними зависит от времени жизни объектов: weak подходит, когда объект может быть уничтожен раньше, а unowned — когда вы уверены, что объект будет жить столько же или дольше ссылки.
Как это работает
В Swift для управления памятью используется подсчёт ссылок (ARC). Каждая сильная ссылка увеличивает счётчик, и объект не освобождается, пока счётчик не станет нулевым. weak и unowned не увеличивают счётчик, поэтому они не препятствуют освобождению объекта. Это позволяет разорвать циклические ссылки, когда два объекта ссылаются друг на друга.
weak— это всегда опциональная ссылка (типSomeClass?). Когда объект освобождается, ARC автоматически устанавливает её вnil. Это безопасно, потому что вы всегда можете проверить наличие значения перед обращением.unowned— это неопциональная ссылка (типSomeClass). Она не обнуляется при освобождении объекта. Если вы обратитесь к ней после освобождения, программа упадёт с ошибкой времени выполнения.
Пример
Рассмотрим классический пример с двумя классами, которые ссылаются друг на друга.
class Person {
var apartment: Apartment?
}
class Apartment {
weak var tenant: Person? // слабая ссылка, чтобы избежать цикла
}Здесь Apartment имеет слабую ссылку на Person. Если Person освободится, tenant станет nil. Это безопасно, потому что квартира может существовать без жильца.
Теперь пример с unowned:
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]для предотвращения циклов.
Похожие вопросы
- В чем суть оптимизации copy on write90%
- что такое Solid72%
- Расскажи о своем опыте72%
- Какие задачи выполнял на прошлом месте работы66%
- Какие есть известные проблемы с многопоточностью63%
- Чем отличаются структуры и классы63%
- Какие знаешь методы жизненного цикла Activity и как они отрабатывают60%
- Для чего нужен data class60%
