Sobes.tech
Middle

iOSтогу кармоо циклдери (retain cycles) эмне?

sobes.tech AI

AIден жооп

Кайталануу циклдары пайда болот, эгер эки же андан көп объект бири-бирине күчтүү шилтемелерге ээ болсо, бул "жабык чынжыр" түзөт. Натыйжада, ар бир объекттин шилтемелер санагычы нөлгө жетпейт жана ал ARC (Automatic Reference Counting) тарабынан бошотулбайт. Бул эс тутумдун агып кетишине алып келет, анткени объекттер колдонулбаса дагы эс тутумда калат.

Мисал:

class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) {
        self.name = name
        print("\(name) ишке киришүүдө")
    }

    deinit {
        print("\(name) бошотулууда")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?

    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) ишке киришүүдө")
    }

    deinit {
        print("Apartment \(unit) бошотулууда")
    }
}

Бул мисалда, эгер Person күчтүү шилтемеге ээ болсо Apartmentка жана Apartment күчтүү шилтемеге ээ болсо Personга, анда бул объекттер бошотулгондо, алар өчүрүлбөйт, анткени алардын шилтемелер санагычтары нөлгө жетпейт.

Кайсы учурда кайталануучу циклдарды чечүү керек:

слабый (weak) же башкача (unowned) шилтемелерди колдонуу.

  • weak: Бул, байланышкан объект nil болушу мүмкүн болгон учурда колдонулат. шилтеме автоматтык түрдө nil болот, объект бошотулганда. Бул опционалдуу.
  • unowned: Бул, байланышкан объекттин ошол же узак жашоо цикли бар экендигин билгенде колдонулат. nil болбойт.

Түзөтүлгөн мисал weak колдонуу менен:

Apartment классынын tenant шилтемесин алсызга өзгөртөлү:

class Apartment {
    let unit: String
    weak var tenant: Person? // weak колдонулуп жатат

    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) ишке киришүүдө")
    }

    deinit {
        print("Apartment \(unit) бошотулууда")
    }
}

Эми, Person объекти бошотулганда, tenant шилтемеси автоматтык түрдө nil болот, бул кайталануучу циклды үзүп, Apartment да бошотулушуна мүмкүндүк берет.

weak жана unowned салыштыруу:

Өзгөчөлүк weak unowned
Шилтеменин түрү Опционалдуу Опционалдуу эмес
nil болушу мүмкүнбү? Ооба, объект бошотулганда Жок
Кайсы учурда колдонуу керек? Объект nil болушу мүмкүн болсо Объект nil болбошу керек болсо
Аткаруу ылдамдыгы Азырынча жайыраак, nil текшерүү үчүн Азырынча тезирээк

Мындан тышкары, кайталануучу циклдар жабдууларда да пайда болушу мүмкүн.

Жабдуулар self жана же өзгөчөлүктөрдү камтыганда, ал күчтүү шилтемени түзө алат. Эгер бул объект ошондой эле күчтүү шилтемеге ээ болсо жабдууга (мисалы, өзгөчөлүк-жабдуусу же делегат аркылуу), анда цикл пайда болот.

Кайсы учурда кайталануучу циклдарды чечүү керек:

capture list колдонуу.

class SomeClass {
    var value = 0

    func doSomethingDelayed() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in // capture list менен weak self
            guard let self = self else { return } // `nil` текшерүү үчүн
            self.value += 1
            print("Кийинки мааниси \(self.value)")
        }
    }
}

Бул мисалда, [weak self] жабдуунун ичинде selfке алсыз шилтемени түзөт, бул кайталануучу циклдарды алдын алат.