Sobes.tech
Junior — Middle

Czy mogą wystąpić trudności lub nieoczekiwane zachowania, jeśli jedno z zamknięć wewnętrznych klasy odwołuje się do jej metod lub właściwości?

sobes.tech AI

Odpowiedź od AI

Tak, podczas korzystania z zamknięć (closures) w obrębie klasy w Swift, mogą wystąpić trudności związane z przechwytywaniem self oraz potencjalnymi cyklami zatrzymania (retain cycles).

Jeśli zamknięcie przechwytuje self bez użycia słabej lub niejawnej referencji ([weak self] lub [unowned self]), może to spowodować, że instancja klasy nie zostanie zwolniona z pamięci, ponieważ zamknięcie utrzymuje silną referencję do self, a self może utrzymywać zamknięcie.

Przykład problemu:

class MyClass {
    var closure: (() -> Void)?
    var value = 10

    func setupClosure() {
        closure = {
            print(self.value) // przechwycenie self
        }
    }

    deinit {
        print("MyClass został zniszczony")
    }
}

var obj: MyClass? = MyClass()
obj?.setupClosure()
obj = nil // MyClass nie zostanie zniszczony z powodu cyklu zatrzymania

Aby tego uniknąć, używa się słabej referencji:

closure = { [weak self] in
    guard let self = self else { return }
    print(self.value)
}

Ważne jest więc staranne zarządzanie przechwytywaniem self w zamknięciach w klasach, aby zapobiec wyciekom pamięci i nieoczekiwanym zachowaniom.