Sobes.tech
Middle

როგორ მუშაობს ავტომატური მეხსიერების მართვის (ARC) მექანიზმი Swift ენისთვის?

sobes.tech AI

პასუხი AI-სგან

ARC (Автоматикалык шилтемелерди эсептөө) автоматтык түрдө класстардын мисалдарына шилтемелерди көзөмөлдөп, башкаруу жүргүзөт. Ал мисалдын ээлеген эсебин бошотуп, эсебин бошотот, эгер ага күчтүү шилтемелер болбосо. ARC гана класстардын мисалдарында иштейт, структуралар же энумдар менен эмес, анткени алар маанилер түрү болуп саналат.

Мисалдар арасындагы үч түрдүү байланыс:

  • Strong (Күчтүү): Мисалга шилтемени көбөйтөт. Бардык шилтемелер боюнча демейки күчтүү.
  • Weak (Слабый): Шилтемени көбөйтпөйт. Күчтүү шилтемелер циклин алдын алуу үчүн колдонулат. weak типтеги шилтемелер ар дайым опционалдуу, анткени мисал кез келген учурда бошотулушу мүмкүн.
  • Unowned (Бошотулбаган): Шилтемени көбөйтпөйт жана байланыштуу мисалдын узактыгы учурдагыдан узунураак болот деп кепилдик берилген учурда колдонулат. Мажбур эмес, бирок бошотулган мисалга кирүү аракетинде иштөө ката чыгарат.

Күчтүү шилтемелер цикли пайда болот, эгер эки же андан көп мисал бири-бирине күчтүү шилтемелерди түзсө, бул ARCтин бошотулушун алдын алат. Бул циклдерди чечүү үчүн weak же unowned шилтемелер колдонулат.

Өлчөмдөрдүн мисалы:

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

    init(name: String) {
        self.name = name
    }

    deinit { // бошотуу учурунда чакырылат
        print("\(name) бошотулууда")
    }
}

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

    init(unit: String) {
        self.unit = unit
    }

    deinit { // бошотуу учурунда чакырылат
        print("Квартира \(unit) бошотулууда")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil // Эч кандай чыгуу жок, анткени цикл түзүлдү

Циклдерди чечүү үчүн weak колдонуу:

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

    init(name: String) {
        self.name = name
    }

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

class Apartment {
    let unit: String
    weak var tenant: Person? // Слабое шилтемени колдонуу

    init(unit: String) {
        self.unit = unit
    }

    deinit {
        print("Квартира \(unit) бошотулууда")
    }
}

var john: Person?
var unit4A: Apartment?

john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil // Person бошотулду
unit4A = nil // Apartment бошотулду

Циклдерди чечүү үчүн unowned колдонуу:

class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) {
        self.name = name
    }

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

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Бошотулбаган шилтеме

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }

    deinit {
        print("Карта #\(number) бошотулууда")
    }
}

var john: Customer?

john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

john = nil // Customer жана CreditCard бошотулду

ARC жана аягында: Аягында, блоктор да циклер түзө алат, класстардын мисалдарын кармап калуу аркылуу. Бул циклдерди алдын алуу үчүн [weak self] же [unowned self] колдонулат:

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

    lazy var asHTML: () -> String = { // lazy, self колдонууга мүмкүндүк берүү үчүн
        [unowned self] in // кармоо тизмеси
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

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

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

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "салам, дүйнө")
print(paragraph!.asHTML())

paragraph = nil // HTMLElement бошотулду