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-ისგან, unowned მითითება არ ხდება 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 // Ապարատը ազատվում է, քանի որ նրա ռեֆերանսների հաշվիչը դարձավ 0