Aula 23: Contagem Automática de Referências (ARC)
A Contagem Automática de Referências (ARC) é um recurso de gerenciamento de memória do Swift que ajuda a administrar a memória do seu aplicativo de forma automática. Diferente do gerenciamento manual de memória, onde você precisa alocar e desalocar objetos explicitamente, o ARC monitora e gerencia o uso da memória por você, garantindo que seu aplicativo mantenha um desempenho ótimo sem vazamentos de memória.
Como o ARC Funciona
No ARC, toda vez que você cria uma nova instância de uma classe, o Swift aloca memória para ela. O ARC mantém um registro do número de referências (referências fortes) a cada instância de classe. Quando o contador de referências cai para zero, significando que não há mais referências fortes para aquela instância, a memória usada por essa instância é liberada.
Referências Fortes
Referências fortes são o tipo de referência padrão no Swift. Toda vez que você atribui um objeto a uma variável ou constante, uma referência forte é criada.
class Pessoa {
var nome: String
init(nome: String) {
self.nome = nome
}
}
var joao: Pessoa? = Pessoa(nome: "João da Silva")
// O contador de referências da instância Pessoa agora é 1
No exemplo acima, a variável joao
mantém uma referência forte à instância de Pessoa
. Quando você posteriormente define joao
como nil
, o contador de referências cai para zero e a memória associada é desalocada.
joao = nil
// O contador de referências cai para 0, a memória é liberada
Referências Fracas
Às vezes, você pode querer evitar ciclos de referência forte, especialmente em cenários onde duas instâncias se referenciam mutuamente. Podemos usar referências fracas para prevenir esse ciclo. Uma referência fraca não aumenta o contador de referências do objeto ao qual ela se refere.
Para declarar uma referência fraca, use a palavra-chave weak
.
class Cachorro {
var dono: Pessoa?
}
class Pessoa {
var cachorro: Cachorro?
}
var joao: Pessoa? = Pessoa(nome: "João da Silva")
var fido: Cachorro? = Cachorro()
joao?.cachorro = fido
fido?.dono = joao
// Aqui, tanto joao quanto fido se referem um ao outro, criando um ciclo de referência forte.
// Quando definimos joao como nil, a instância de Cachorro nunca seria desalocada porque mantém uma referência forte ao seu dono.
joao = nil // O contador de referências não cai para 0 para a instância de Cachorro
Para evitar esse ciclo de referência forte, declaramos dono
em Cachorro
como uma referência fraca:
class Cachorro {
weak var dono: Pessoa?
}
class Pessoa {
var cachorro: Cachorro?
}
var joao: Pessoa? = Pessoa(nome: "João da Silva")
var fido: Cachorro? = Cachorro()
joao?.cachorro = fido
fido?.dono = joao
joao = nil // Agora, a instância de Cachorro é desalocada, pois o contador de referências cai para 0
Referências Não Propriedadas
Referências não propriedade são semelhantes às referências fracas, pois não aumentam o contador de referências. No entanto, as referências não propriedade devem sempre ter um valor, o que significa que, se você tentar acessar uma referência não propriedade após sua instância ter sido desalocada, isso levará a uma falha em tempo de execução.
Use unowned
quando você sabe que o objeto referenciado nunca se tornará nil durante a vida do objeto que detém a referência.
class Apartamento {
var inquilino: Pessoa
init(inquilino: Pessoa) {
self.inquilino = inquilino
}
}
class Pessoa {
var apartamento: Apartamento
init(apartamento: Apartamento) {
self.apartamento = apartamento
}
}
// Cria instâncias
var joao: Pessoa? = Pessoa(apartamento: Apartamento(inquilino: Pessoa(apartamento: Apartamento(inquilino: Pessoa(nome: "João")))))
Resumo do Gerenciamento de Memória
- Referências fortes aumentam o contador de referências de um objeto. A memória do objeto é liberada quando o contador chega a zero.
- Referências fracas não aumentam o contador de referências, permitindo a desalocação sem criar ciclos de referência fortes.
- Referências não propriedade também não aumentam o contador de referências, mas esperam que o objeto sempre exista durante seu tempo de vida.
Conclusão
A Contagem Automática de Referências simplifica o gerenciamento de memória no Swift, permitindo que os desenvolvedores se concentrem mais na construção de recursos do que na gestão da memória. Compreender os conceitos de referências fortes, fracas e não propriedade é essencial para gerenciar a memória de forma eficaz e evitar vazamentos de memória em seus aplicativos.