Sobes.tech
Middle

Ako zabrániť vzniku cyklu udržiavania (retain cycle) v iOS?

sobes.tech AI

Odpoveď od AI

Cyklus držania sa prevencijom pravilnim korišćenjem slabih (weak) ili bezuslovnih nedržavajućih (unowned) referenci.

Slabe reference (weak):

  • Ne povećavaju brojač referenci objekta.
  • Mogu postati nil.
  • Koriste se kada jedan objekat može postojati nezavisno od drugog (na primer, delegat).
class DelegateExample {
    weak var delegate: SomeDelegateType? // Slaba referenca na delegata
}

Bezuslovne nedržavajuće reference (unowned):

  • Ne povećavaju brojač referenci objekta.
  • Garantovano nisu nil.
  • Koriste se kada jedan objekat jasno poseduje drugi, ali zavisni objekat može postojati samo zajedno sa vlasnikom (na primer, zatvarači, zarobljavajući self u klasi, gde zatvarač jasno "pripada" instanci klase). Pri pristupu unowned referenci, ako je objekat već oslobođen, dolazi do greške u vreme izvršavanja.
class Owner {
    var closure: (() -> Void)?

    func setupClosure() {
        closure = { [unowned self] in // Bezuslovna nedržavajuća referenca na self
            // Korišćenje self
            print("Using unowned self")
        }
    }
}

Korišćenje u zatvaračima: Zatvarači mogu izazvati cikluse držanja ako zarobe instance klasa jakom referencom, a taj primerak klase takođe sadrži jaku referencu na zatvarač. Za sprečavanje koriste se liste zarobljavanja (capture lists) na početku zatvarača:

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

    lazy var asHTML: () -> String = { [weak self] in // Slaba referenca na self
        guard let strongSelf = self else {
            return "" // Obrada slučaja kada je self već `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) se deaktivira")
    }
}

Izbor između weak i unowned zavisi od semantike odnosa između objekata:

  • weak: kada referenca može postati nil tokom životnog veka objekta na koji se odnosi.
  • unowned: kada je objekat na koji se odnosi garantovano duži ili jednak trajanja od objekta koji na njega referiše, i referenca nikada neće postati nil.