Sobes.tech
Intern

Cos'è un garbage collector?

sobes.tech AI

Risposta dell'AI

Su iOS, non esiste un tradizionale raccoglitore di spazzatura. Al suo posto, viene utilizzato il meccanismo di Riferimento Automatico (ARC).

  • Meccanismo automatico: ARC conta automaticamente i riferimenti forti agli oggetti.
  • Rilascio della memoria: Quando il conteggio dei riferimenti forti a un oggetto raggiunge zero, ARC libera la memoria allocata.
  • Prevenzione delle perdite: L'uso corretto di riferimenti forti, deboli e non posseduti (unowned) permette di prevenire perdite di memoria e cicli di riferimenti.

Tipi di riferimenti in ARC:

  • Forti (strong): Aumenta il contatore di riferimenti. È il valore predefinito.
  • Deboli (weak): Non aumenta il contatore di riferimenti. Diventa automaticamente nil quando l'oggetto viene deallocato. Usato per prevenire cicli di riferimenti forti. Viene dichiarato come un tipo opzionale.
  • Non posseduti (unowned): Non aumenta il contatore di riferimenti. È garantito che l'oggetto a cui si riferisce esista durante tutto il ciclo di vita del riferimento non posseduto. Non è opzionale. Usato quando due oggetti hanno una relazione forte reciproca, ma uno di essi ha un ciclo di vita più breve.

Vantaggi di ARC:

  • Prevedibilità: La liberazione della memoria avviene in modo deterministico, non appena l'oggetto non viene più utilizzato.
  • Prestazioni: Non ci sono costi aggiuntivi per il garbage collector in background, che può causare pause.
  • Semplicità: Lo sviluppatore non deve gestire manualmente la memoria nella maggior parte dei casi, ma deve comprendere i principi del conteggio dei riferimenti per prevenire perdite.

Esempio di ciclo di riferimenti forti:

class Person {
    let name: String
    var apartment: Apartment? // riferimento forte ad Apartment

    init(name: String) { self.name = name }
    deinit { print("\(name) viene deallocato") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // riferimento debole a Person per prevenire ciclo

    init(unit: String) { self.unit = unit }
    deinit { print("Appartamento \(unit) viene deallocato") }
}

var john: Person?
var unit4A: Apartment?

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

john!.apartment = unit4A
unit4A!.tenant = john // L'uso di weak qui è critico

john = nil
unit4A = nil
// Senza tenant weak: Sia john che unit4A non verrebbero deallocati.
// Con tenant weak: Sia john che unit4A vengono deallocati correttamente.