Назад к вопросам
Middle
100
questionbank
В чем заключается разница между 'weak' и 'unowned' в Swift?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
weak и unowned используются для разрешения циклических ссылок, но отличаются по своему поведению и применению.
| Свойство | 'weak' | 'unowned' |
|---|---|---|
| Тип | Опционал (Optional) | Не опционал |
| Lifetime | Может стать nil |
Гарантированно имеет значение |
| Гарантия существования | Нет | Да, до окончания Scope |
| Применение | Когда возможна ситуация, что связанный объект будет деаллоцирован первым. | Когда связанный объект будет деаллоцирован либо одновременно с текущим, либо позже. |
| Пример | Делегат (delegate) | Связь Родитель-Ребенок (Parent-Child) |
weak:
- Используется, когда один объект может существовать без ссылки на другой, или когда одному из объектов разрешено быть
nil. - Автоматически становится
nil, когда объект, на который он ссылается, деаллоцируется. - Должен быть объявлен как опциональный тип.
class Person {
let name: String
var apartment: Apartment?
init(name: String) { self.name = name }
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
weak var tenant: Person? // cyclic reference solved with weak
init(unit: String) { self.unit = unit }
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john // No strong reference cycle
john = nil // Person object is deallocated
// unit4A?.tenant is now nil
unit4A = nil // Apartment object is deallocated
unowned:
- Используется, когда одному объекту принадлежит другой, и оба должны существовать одновременно или связанный объект переживет текущий.
- Гарантируется, что всегда имеет значение. При попытке доступа после деаллокации объекта произойдет сбой выполнения (runtime error).
- Объявляется как не опциональный тип.
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // cyclic reference solved with unowned
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
var john: Customer? = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // No strong reference cycle
john = nil // Customer and CreditCard objects are deallocated
Выбор между weak и unowned зависит от того, имеет ли связанный объект возможность стать nil в течение жизни текущего объекта. Если да, используйте weak. Если нет, используйте unowned.