Sobes.tech
Middle

Kako sprečiti nastanak ciklusa zadržavanja (retain cycle) u iOS?

sobes.tech АИ

Одговор од АИ

Цикли задржавања спречавају се правилним коришћењем слабих (weak) или безусловних не задржавајућих (unowned) референци.

Слабе референце (weak):

  • Не повећавају бројач референци објекта.
  • Нулле (могу постати nil).
  • Користе се када један објекат може постојати независно од другог (на пример, делегат).
class DelegateExample {
    weak var delegate: SomeDelegateType? // Слаба референца на делегата
}

Безусловне не задржавајуће референце (unowned):

  • Не повећавају бројач референци објекта.
  • Гарантовано нису nil.
  • Користе се када један објекат јасно поседује други, али зависни објекат може постојати само заједно са власником (на пример, затварачи, заробљавајући self у класи, где затварање јасно "припаја" екземпляру класе). При приступу unowned референци, ако је објекат већ ослобођен, долази до грешке у време извршавања.
class Owner {
    var closure: (() -> Void)?

    func setupClosure() {
        closure = { [unowned self] in // Безусловна не задржавајућа референца на self
            // Коришћење self
            print("Using unowned self")
        }
    }
}

Користење у затварањима: Затварања могу изазвати циклусе задржавања ако заробе примерке класа јаком референцом, а тај примерак класе такође садржи јаку референцу на затварање. За спречавање користе се листе заробљавања (capture lists) на почетку затварања:

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

    lazy var asHTML: () -> String = { [weak self] in // Слаба референца на self
        guard let strongSelf = self else {
            return "" // Обрада случаја када је self већ `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) се деактивира")
    }
}

Избор између weak и unowned зависи од семантике односа између објеката:

  • weak: када референца може постати nil током животног века објекта на који се односи.
  • unowned: када је објекат на који се односи гарантовано дужи или једнако дуг као и објекат који на њега реферише, и референца никада неће постати nil.