0Pricing
Swift Academy · Lekcja

Listy przechwytywania i weak self

Unikanie cykli silnych referencji za pomocą [weak self].

Listy przechwytywania i weak self to bezpłatna lekcja Swift Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Swift Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Swift Academy zawiera 4 lekcji w sumie.

Ryzyko cyklu silnych referencji

Gdy obiekt przechowuje uciekające domknięcie, które silnie przechwytuje self, każde z nich utrzymuje drugie przy życiu na zawsze — powstaje cykl silnych referencji, powodujący wyciek pamięci.

Cykl silnych referencji

Domknięcie silnie przechwytuje self, a self przechowuje domknięcie — żaden z tych elementów nigdy nie zostaje zwolniony:

class Owner {
    var onEvent: (() -> Void)?
    func setup() {
        onEvent = { print(self.describe()) }  // strong self -> cycle
    }
    func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?()  // "Owner"  (but leaks)

Listy przechwytywania

Lista przechwytywania na początku domknięcia { [weak self] in ... } określa sposób przechowywania każdego przechwyconego odwołania: jako weak lub unowned, zamiast silnego odwołania.

Przerywanie cyklu za pomocą weak self

[weak self] przechwytuje self jako wartość opcjonalną, która nie utrzymuje go przy życiu:

class Owner {
    var onEvent: (() -> Void)?
    func setup() {
        onEvent = { [weak self] in
            print(self?.describe() ?? "gone")
        }
    }
    func describe() -> String { "Owner" }
}
let o = Owner(); o.setup()
o.onEvent?()  // "Owner"  (no cycle)

weak sprawia, że self jest opcjonalne

W przypadku [weak self] wartość self staje się typu Self?, więc należy ją rozpakować:

class Worker {
    var tag = "W"
    lazy var job: () -> Void = { [weak self] in
        guard let self = self else { return }
        print(self.tag)
    }
}
let w = Worker()
w.job()  // "W"

Wzorzec guard let self

Należy ponownie przypisać self na początku, aby w pozostałej części domknięcia używać silnego, nieopcjonalnego odwołania:

class Service {
    var name = "S"
    lazy var run: () -> Void = { [weak self] in
        guard let self else { return }
        print(self.name)
        print("still \(self.name)")
    }
}
Service().run()  // "S" / "still S"

weak a unowned

weak daje wartość opcjonalną i jest bezpieczne, jeśli obiekt może już nie istnieć. unowned nie jest opcjonalne i działa szybciej, ale powoduje awarię po uzyskaniu dostępu do obiektu, który został zwolniony — należy go używać tylko wtedy, gdy ma Pan/Pani gwarancję, że self będzie istnieć dłużej niż domknięcie.

Używanie unowned

Należy wybrać unowned, gdy domknięcie nie może istnieć dłużej niż self:

class Timer2 {
    var ticks = 0
    lazy var tick: () -> Void = { [unowned self] in
        self.ticks += 1
    }
}
let t = Timer2()
t.tick(); t.tick()
print(t.ticks)  // 2

Przechwytywanie konkretnych właściwości

Należy przechwytywać tylko potrzebne elementy zamiast całego self — czasami pozwala to całkowicie uniknąć cyklu:

class VM {
    let id = 42
    lazy var printer: () -> Void = { [id] in print(id) }
}
VM().printer()  // 42

Domknięcia nieuciekające nie potrzebują weak

Synchroniczne domknięcia nieuciekające (takie jak map) nie powodują cykli, więc silne przechwytywanie self jest w ich przypadku bezpieczne:

class Calc {
    let factor = 3
    func scale(_ xs: [Int]) -> [Int] {
        xs.map { $0 * self.factor }   // safe, non-escaping
    }
}
print(Calc().scale([1, 2]))  // [3, 6]

Praktyczna zasada

Należy używać [weak self] w przechowywanych lub uciekających domknięciach, które odwołują się do self. Po unowned należy sięgać tylko wtedy, gdy ma Pan/Pani gwarancję, że self będzie istnieć. W przypadku domknięć nieuciekających listy przechwytywania nie są potrzebne.

class P {
    var n = "P"
    var stored: (() -> Void)?
    func arm() { stored = { [weak self] in print(self?.n ?? "-") } }
}
let p = P(); p.arm(); p.stored?()  // "P"

Szybkie sprawdzenie

Dlaczego w przechowywanym uciekającym domknięciu używa się [weak self]?

Podsumowanie

Poznał(a) Pan/Pani listy przechwytywania:

  • Silne self w przechowywanym uciekającym domknięciu tworzy cykl silnych referencji (wyciek pamięci)
  • [weak self] przerywa cykl; self staje się opcjonalne — należy użyć guard let self
  • unowned nie jest opcjonalne i działa szybciej, ale powoduje awarię, jeśli self już nie istnieje
  • Domknięcia nieuciekające nie potrzebują list przechwytywania

Dalej: autodomknięcia.

Często zadawane pytania

Czy lekcja „Listy przechwytywania i weak self” jest bezpłatna?

Tak — pełny tekst „Listy przechwytywania i weak self” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Swift Academy, przejdź na CoddyKit PRO. Kurs Swift Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Listy przechwytywania i weak self”?

Unikanie cykli silnych referencji za pomocą [weak self]. Ćwiczysz Swift Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Swift Academy?

Nie wymagamy żadnego doświadczenia. Swift Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Listy przechwytywania i weak self”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Swift Academy?

Tak. Każda lekcja Swift Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Przechwytywanie wartości przez referencję
  2. Domknięcia uciekające
  3. Listy przechwytywania i weak self
  4. Autodomknięcia
← Powrót do Swift Academy