Sobes.tech
Middle

Μιλήστε μας για τη διαχείριση μνήμης στο iOS.

sobes.tech AI

Απάντηση από AI

Το iOS χρησιμοποιεί αυτόματη μέτρηση αναφορών (ARC) για τη διαχείριση μνήμης. Το ARC απελευθερώνει αυτόματα αντικείμενα μόλις σταματούν να αναφέρονται σε αυτά.

Βασικές έννοιες:

  • Ισχυρή Αναφορά: Αυξάνει τον μετρητή αναφορών ενός αντικειμένου. Το αντικείμενο δεν θα απελευθερωθεί όσο υπάρχουν ισχυρές αναφορές σε αυτό.
  • Αδύναμη Αναφορά: Δεν αυξάνει τον μετρητή αναφορών. Χρησιμοποιείται για την αποφυγή κυκλωμάτων ισχυρών αναφορών. Αναφέρεται σε ένα αντικείμενο που μπορεί να απελευθερωθεί. Αν το αντικείμενο απελευθερωθεί, η αδύναμη αναφορά γίνεται nil.
  • Ανεξάρτητη Αναφορά (unowned): Παρόμοια με την αδύναμη, δεν αυξάνει τον μετρητή αναφορών. Χρησιμοποιείται όταν το αντικείμενο στο οποίο αναφέρεται έχει την ίδια ή μεγαλύτερη διάρκεια ζωής. Η ανεξάρτητη αναφορά δεν γίνεται nil όταν το αντικείμενο απελευθερώνεται. Η πρόσβαση σε ένα απελευθερωμένο αντικείμενο μέσω ανεξάρτητης αναφοράς προκαλεί σφάλμα εκτέλεσης.

Κύκλοι ισχυρών αναφορών (Retain Cycles): Προκύπτουν όταν δύο ή περισσότερα αντικείμενα έχουν ισχυρές αναφορές το ένα στο άλλο, εμποδίζοντας την απελευθέρωσή τους. Λύνονται με αδύναμες ή ανεξάρτητες αναφορές.

Παράδειγμα κύκλου ισχυρών αναφορών και η λύση του:

class Person {
    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: Person? // Χρησιμοποιεί αδύναμη αναφορά για να αποτρέψει κύκλο

    init(unit: String) {
        self.unit = unit
        print("Δωμάτιο \(unit) αρχικοποιείται")
    }

    deinit {
        print("Δωμάτιο \(unit) απελευθερώνεται")
    }
}

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

john!.apartment = unit4A
unit4A!.tenant = john // Εδώ δημιουργείται κύκλος

john = nil
unit4A = nil
// Οι μέθοδοι deinit δεν καλούνται λόγω κύκλου

Λύση με weak:

class Person {
    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: Person? // Χρησιμοποιεί αδύναμη αναφορά για να αποτρέψει κύκλο

    init(unit: String) {
        self.unit = unit
        print("Δωμάτιο \(unit) αρχικοποιείται")
    }

    deinit {
        print("Δωμάτιο \(unit) απελευθερώνεται")
    }
}

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

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

john = nil
unit4A = nil
// Και τα δύο αντικείμενα απελευθερώνονται σωστά

Διαφορά μεταξύ unowned και weak:

  • Χρησιμοποιήστε weak όταν η αναφορά μπορεί να γίνει nil (το αντικείμενο μπορεί να απελευθερωθεί πρώτο).
  • Χρησιμοποιήστε unowned όταν η αναφορά πάντα θα έχει τιμή (το αντικείμενο στο οποίο αναφέρεται έχει την ίδια ή μεγαλύτερη διάρκεια ζωής).

Closures και κύκλοι αναφορών:

Οι closures μπορούν να καταγράψουν αναφορές σε αντικείμενα, δημιουργώντας κύκλους ισχυρών αναφορών. Αυτό λύνεται με λίστα καταγραφής (capture list).

Παράδειγμα:

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

    lazy var asHTML: () -> String = {
        [weak self] in // Καταγραφή `self` αδύναμη
        guard let self = self else {
            return ""
        }
        var html = "<\(self.name)"
        if let text = self.text {
            html += ">\(text)</\(self.name)>"
        } else {
            html += " />"
        }
        return html
    }

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

    deinit {
        print("\(name) απελευθερώνεται")
    }
}

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())

paragraph = nil
// Το αντικείμενο απελευθερώνεται

Αποσφαλμάτωση μνήμης:

  • Memory Graph Debugger: Στο Xcode, οπτικοποιεί τις συνδέσεις μεταξύ αντικειμένων και εντοπίζει κύκλους ισχυρών αναφορών.
  • Instruments (Allocations, Leaks): Εργαλεία για την παρακολούθηση της κατανομής και απελευθέρωσης μνήμης, και την ανίχνευση διαρροών.