Sobes.tech
Intern

O que é um coletor de lixo (garbage collector)?

sobes.tech IA

Resposta da IA

No iOS, é utilizado o ARC (Contagem Automática de Referências) — um mecanismo de contagem automática de referências que não é um coletor de lixo tradicional. Em vez de escanear a memória periodicamente, o ARC gere automaticamente a memória inserindo chamadas a retain, release e autorelease no código durante a compilação.

Princípio de funcionamento do ARC:

  • Cada objeto tem um contador de referências.
  • Ao criar um objeto ou atribuir uma referência forte, o contador aumenta (retain).
  • Ao definir uma referência forte para nil ou sair do escopo, o contador diminui (release).
  • Quando o contador chega a zero, o objeto é liberado da memória.

Vantagens do ARC:

  • Liberação de memória determinista (sabe-se quando um objeto será removido).
  • Sem pausas relacionadas ao coletor de lixo tradicional.
  • Alto desempenho.

Desvantagens do ARC:

  • Referências cíclicas ( ciclos de retenção) podem causar vazamentos de memória se não forem usadas referências fracas (weak) ou não possuídas (unowned).

Exemplo de referência cíclica e sua solução:

class Person {
    let name: String
    var apartments: [Apartment] = [] // Referência forte ao Apartment
    init(name: String) { self.name = name }
    deinit { print("\(name) está sendo desalojado") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // Referência fraca ao Person
    init(unit: String) { self.unit = unit }
    deinit { print("Apartamento \(unit) está sendo desalojado") }
}

// Criando uma referência cíclica
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")

john?.apartments.append(unit4A!)
unit4A?.tenant = john

// Atribuir a nil não liberta a memória devido ao ciclo
john = nil
unit4A = nil
// Nenhuma mensagem de deinit será exibida

// Solução usando referência fraca
class FixedPerson {
    let name: String
    var apartments: [FixedApartment] = []
    init(name: String) { self.name = name }
    deinit { print("\(name) está sendo desalojado") }
}

class FixedApartment {
    let unit: String
    weak var tenant: FixedPerson? // Referência fraca ao Person
    init(unit: String) { self.unit = unit }
    deinit { print("Apartamento \(unit) está sendo desalojado") }
}

var fixedJohn: FixedPerson? = FixedPerson(name: "John Appleseed")
var fixedUnit4A: FixedApartment? = FixedApartment(unit: "4A")

fixedJohn?.apartments.append(fixedUnit4A!)
fixedUnit4A?.tenant = fixedJohn

// Atribuir a nil agora liberta a memória
fixedJohn = nil
fixedUnit4A = nil
// As mensagens de deinit serão exibidas

Ao contrário dos coletores de lixo tradicionais (por exemplo, em Java ou Python), que pausam a execução do programa para procurar e liberar objetos não utilizados, o ARC funciona de forma mais eficiente e previsível no contexto do desenvolvimento móvel.