Czym jest unowned?
sobes.tech AI
Odpowiedź od AI
unowned — to słowo kluczowe w Swift do deklarowania słabej referencji. Używa się go, gdy dwa obiekty mają silny związek i ich cykle życia są od siebie zależne, ale chcemy uniknąć cyklicznych referencji, które mogą uniemożliwić zwolnienie pamięci.
Główne właściwości i różnice w stosunku do weak:
- Nie opcjonalny: Referencja
unownednie będzienilprzez cały czas życia obiektu, do którego się odnosi. - Silny związek: Używa się go, gdy jeden obiekt posiada inny, i oba zawsze istnieją razem.
- Podczas zwalniania: Jeśli obiekt, na który wskazuje referencja
unowned, zostanie zwolniony z pamięci przed użyciem referencji, spowoduje to błąd w czasie działania (runtime error). Należy upewnić się, że obiekt, na który się odnosi, istnieje dłużej niż sama referencja. - Zastosowanie: Najczęściej używany dla delegatów, gdy delegat zawsze istnieje dłużej niż obiekt, który go wywołuje, lub w zamknięciach (closures), aby uniknąć cyklicznych referencji do
self, gdy zamknięcie nie przechwytuje silnej referencji naself.
Przykład użycia w zamknięciu:
// swift
class MyClass {
var name: String
var closure: (() -> Void)?
init(name: String) {
self.name = name
}
func setupClosure() {
closure = { [unowned self] in // użycie unowned self
print("Moje imię to \(self.name)")
}
}
deinit {
print("\(name) został zwolniony")
}
}
Przykład użycia dla delegata (chociaż weak jest częściej używany dla delegatów, unowned jest również możliwy, jeśli delegat gwarantuje dłuższe życie):
// swift
protocol MyDelegate: AnyObject { // AnyObject wymaga typu referencyjnego
func doSomething()
}
class DataSource {
unowned var delegate: MyDelegate // referencja `unowned` do delegata
init(delegate: MyDelegate) {
self.delegate = delegate
}
func performAction() {
delegate.doSomething()
}
deinit {
print("DataSource został zwolniony")
}
}
class MyController: MyDelegate {
var dataSource: DataSource?
override init() {
super.init()
dataSource = DataSource(delegate: self)
}
func doSomething() {
print("Metoda delegata wywołana")
}
deinit {
print("MyController został zwolniony")
}
}
Wybór między weak a unowned zależy od tego, czy referencja jest opcjonalna i czy obiekt, na który się odnosi, istnieje gwarantowanie do końca życia referencji. Jeśli istnieje możliwość, że obiekt zostanie zwolniony przed użyciem referencji, należy użyć weak. Jeśli gwarancja istnienia jest zapewniona, a referencja nie powinna być opcjonalna, można użyć unowned.