Sobes.tech
Middle

Hogyan lehet megelőzni a retention cycle (megőrzési ciklus) kialakulását iOS-ben?

sobes.tech MI

Válasz az MI-től

A tartós ciklusok elkerülése érdekében a gyenge (weak) vagy az inconditionális (unowned) hivatkozások helyes használata szükséges.

Gyenge hivatkozások (weak):

  • Nem növelik az objektum hivatkozásszámát.
  • nullázhatók (nil lehetnek).
  • Olyankor használják, amikor egy objektum függetlenül létezhet egy másiktól (például, egy delegált).
class DelegateExample {
    weak var delegate: SomeDelegateType? // Gyenge hivatkozás a delegátra
}

Inconditionális unowned hivatkozások (unowned):

  • Nem növelik az objektum hivatkozásszámát.
  • Garantáltan nem nullák (non-nil).
  • Akkor használják, amikor egy objektum kifejezetten másikat birtokol, de az függő objektum csak a tulajdonossal együtt létezhet (például, záradékok, amelyek self-et fogják, egy osztályban, ahol a záradék "tartozik" az osztály példányához). Az unowned hivatkozás elérésénél, ha az objektum már felszabadult, futási időben hiba lép fel.
class Owner {
    var closure: (() -> Void)?

    func setupClosure() {
        closure = { [unowned self] in // Kifejezett `unowned` hivatkozás self-re
            // Self használata
            print("Unowned self használata")
        }
    }
}

Használat záradékokban: A záradékok akkor hozhatnak létre tartási ciklusokat, ha példányokat erős hivatkozással foglalnak, és ez a példány is erős hivatkozást tartalmaz a záradékra. Ennek elkerülése érdekében a záradék elején foglalási listákat (capture lists) használnak:

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

    lazy var asHTML: () -> String = { [weak self] in // Gyenge hivatkozás self-re
        guard let strongSelf = self else {
            return "" // Az eset kezelése, ha self már 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) felszabadul")
    }
}

A weak és unowned közötti választás az objektumok közötti kapcsolatok szemantikájától függ:

  • weak: amikor a hivatkozás az objektum életciklusa során nil-ré válhat.
  • unowned: amikor a hivatkozott objektum garantáltan hosszabb vagy ugyanannyi ideig létezik, mint a hivatkozó, és a hivatkozás soha nem lesz nil.