Sobes.tech
Middle

Kaip išvengti retencijos ciklo (retain cycle) iOS?

sobes.tech AI

Atsakymas iš AI

Atsargiai naudojant silpnus (weak) arba be sąlygų (unowned) nuorodų ciklai yra išvengiami.

Silpnos nuorodos (weak):

  • Nepadidina objekto nuorodų skaitiklio.
  • Gali tapti nil.
  • Naudojamos, kai vienas objektas gali egzistuoti nepriklausomai nuo kito (pavyzdžiui, delegatas).
class DelegateExample {
    weak var delegate: SomeDelegateType? // Silpna nuoroda į delegatą
}

Be sąlygų (unowned) nuorodos:

  • Nepadidina objekto nuorodų skaitiklio.
  • Garantuoja, kad nėra nil.
  • Naudojamos, kai vienas objektas aiškiai priklauso kitam, bet priklausomas objektas gali egzistuoti tik kartu su savininku (pavyzdžiui, uždarymai, įtvirtinantys self klasėje, kur uždarymas aiškiai "priklauso" klasei). Prieš pasiekiant unowned nuorodą, jei objektas jau atlaisvintas, įvyksta klaida vykdymo metu.
class Owner {
    var closure: (() -> Void)?

    func setupClosure() {
        closure = { [unowned self] in // Be sąlygų nevaldomas nuoroda į self
            // Naudojimas self
            print("Naudojant unowned self")
        }
    }
}

Naudojimas uždarymuose: Uždarymai gali sukelti ciklus, jei jie įtvirtina klasių egzempliorius stiprią nuorodą, ir šis egzempliorius taip pat turi stiprią nuorodą į uždarymą. Norint to išvengti, naudojami įtvirtinimo sąrašai (capture lists) pradžioje:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = { [weak self] in // Silpna nuoroda į self
        guard let strongSelf = self else {
            return "" // Kai self jau `nil`
        }
        if let text = strongSelf.text {
            return "<\(strongSelf.name)>\(text)</\(strongSelf.name)>"
        } else {
            return "<\(strongSelf.name)/>"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) yra išjungtas")
    }
}

Pasirinkimas tarp weak ir unowned priklauso nuo santykių semantikos:

  • weak: kai nuoroda gali tapti nil per objekto gyvavimo ciklą.
  • unowned: kai objektas, į kurį nuoroda, garantuotai egzistuoja ilgiau arba tiek pat, kiek objektas, kuris į jį nuoroda, ir nuoroda niekada nebus nil.