Middle
Como é que previnem vazamentos de memória nos seus projetos?
sobes.tech IA
Resposta da IA
Utilizo várias abordagens:
- ARC (Contagem Automática de Referências): É o mecanismo principal de gestão de memória em Swift e Objective-C. Conta automaticamente as referências aos objetos e os liberta quando o número de referências chega a zero.
- Evitar ciclos de referências fortes: É a causa mais comum de fugas de memória. Uso referências
weakouunownedpara quebrar ciclos. Isto acontece frequentemente ao trabalhar com delegados e closures. - Ferramentas de profiling: Uso regularmente ferramentas do Xcode, como Instruments (Allocator, Leaks), para detectar fugas.
- Verificação de closures: Reviso cuidadosamente as closures, especialmente ao capturar
self, usando listas de captura[weak self]ou[unowned self]. - Cancelar inscrições de notificações: Cancelo a inscrição de
NotificationCentere observadores KVO ao destruir objetos. - Remover observadores e temporizadores: Desativo e anulo temporizadores inválidos e removo observadores quando já não são necessários.
- Gestão de recursos: Gerencio corretamente recursos como ficheiros, sockets e bases de dados, fechando-os e libertando-os atempadamente.
- Revisões de código: Realizo revisões de código regularmente, incluindo para detectar possíveis problemas de gestão de memória.
Exemplo de uso de [weak self] numa closure:
class DataFetcher {
var completionHandler: (() -> Void)?
func fetchData() {
// Uso de weak self para evitar ciclo forte
DispatchQueue.global().async { [weak self] in
// Simulação de obtenção de dados
sleep(1)
DispatchQueue.main.async {
// Verificação de nil antes de usar self
self?.completionHandler?()
}
}
}
}
class ViewController {
var fetcher: DataFetcher?
func setupFetcher() {
fetcher = DataFetcher()
fetcher?.completionHandler = {
// Aqui, self pode ser fraco se fetcher ainda existir
print("Dados obtidos no ViewController")
}
}
deinit {
print("ViewController desinicializado")
}
}
Exemplo de uso de weak para um delegado:
protocol DataProcessorDelegate: AnyObject { // AnyObject garante o tipo de referência e impede ciclos fortes com tipos de valor
func processData(_ data: String)
}
class DataProcessor {
weak var delegate: DataProcessorDelegate? // Uso de weak para o delegado
func process(_ data: String) {
delegate?.processData(data)
}
}
class AnotherViewController: DataProcessorDelegate {
let processor = DataProcessor()
init() {
processor.delegate = self
}
func processData(_ data: String) {
print("Processando dados: \(data)")
}
deinit {
print("AnotherViewController desinicializado")
}
}