Sobes.tech
Middle

Ի՞նչ է ավտոմատ հղումների հաշվարկը։

sobes.tech AI

Պատասխան AI-ից

Ավտոմատ ռեֆերանսների հաշվարկը (Automatic Reference Counting, ARC) մեխանիզմ է հիշողության կառավարման Swift և Objective-C-ում, որը ավտոմատ կերպով հետևում և ազատում է օբյեկտների համար հատկացված հիշողությունը: Յուրաքանչյուր դասի օրինակ ունի ռեֆերանսների հաշվիչ, որը մեծանում է, երբ ստեղծվում է ուժեղ ռեֆերանս օբյեկտի վրա և նվազում է, երբ այն հեռացվում է: Երբ ռեֆերանսների հաշվիչը հասնում է զրոյի, ARC-ը ավտոմատ կերպով ազատում է օբյեկտը և այն զբաղեցրած հիշողությունը:

ARC-ը կանխում է հիշողության արտահոսքերը և կրկնակի ազատումը, պարզեցնելով հիշողության կառավարմանը՝ համեմատած ձեռքով կառավարմամբ (օրինակ՝ Objective-C-ում առանց ARC-ի):

Կան երեք տեսակի ռեֆերանսներ:

  1. Strong (ուժեղ): մեծացնում է օբյեկտի ռեֆերանսների հաշվիչը: Սա հիմնական ռեֆերանսի տեսակն է:
  2. Weak (թույլ): չի մեծացնում ռեֆերանսների հաշվիչը: Օգտագործվում է ուժեղ ռեֆերանսային ցիկլերի կանխարգելման համար, երբ երկու օբյեկտներ միմյանց վրա ուժեղ ռեֆերանսներ ունեն: Թույլ ռեֆերանսը nil կդառնա, եթե այն օբյեկտը, որի վրա ցույց է տալիս, ազատվի: Դիֆայնվում է weak բանալիով:
  3. Unowned (անվեր): չի մեծացնում ռեֆերանսների հաշվիչը և միշտ ունի արժեք: Օգտագործվում է, երբ հայտնի է, որ ռեֆերանսը միշտ ցույց է տալու օբյեկտին, մինչ օբյեկտը գոյություն ունի: Վերածնվում է weak-ից տարբեր, քանի որ չի դառնում nil և կարող է հանգեցնել սխալի, եթե փորձեք մուտք գործել օբյեկտը նրա ազատումից հետո: Դիֆայնվում է unowned բանալիով:

Օրինակ ուժեղ ռեֆերանսային ցիկլի:

class Human {
    let name: String
    var apartment: Apartment? // Ուժեղ ռեֆերանս օպցիոնալ `Apartment`-ին
    init(name: String) {
        self.name = name
        print("\(name) սկսում է ինիցիալիզացվել")
    }
    deinit {
        print("\(name) վերջանում է դեինիցիալիզացվել")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Ուժեղ ռեֆերանս օպցիոնալ `Human`-ին
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) սկսում է ինիցիալիզացվել")
    }
    deinit {
        print("Apartment \(unit) վերջանում է դեինիցիալիզացվել")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil
unit4A = nil
// Ոչ "John Appleseed սկսում է ինիցիալիզացվել", ոչ "Apartment 4A սկսում է ինիցիալիզացվել" չի ցուցադրվի՝ ուժեղ ռեֆերանսային ցիկլի պատճառով

Հարցը լուծելու համար՝ օգտագործելով weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) սկսում է ինիցիալիզացվել")
    }
    deinit {
        print("\(name) վերջանում է դեինիցիալիզացվել")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Թույլ ռեֆերանս
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) սկսում է ինիցիալիզացվել")
    }
    deinit {
        print("Apartment \(unit) վերջանում է դեինիցիալիզացվել")
    }
}

var john: Human?
var unit4A: Apartment?

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

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

john = nil // John ազատվում է, քանի որ նրա ռեֆերանսների հաշվիչը դարձավ 0
unit4A = nil // Apartment-ը ազատվում է, քանի որ նրա ռեֆերանսների հաշվիչը դարձավ 0