Principais erros de desenvolvedores Swift iniciantes: nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Principais erros de desenvolvedores Swift iniciantes: nível avançado



Ao passar da escrita de telas simples em SwiftUI para a criação de aplicações multithread complexas com arquitetura personalizada, o número de armadilhas aumenta drasticamente. Muitos desenvolvedores, após dominarem a sintaxe básica do Swift, acreditam estar prontos para produção, mas cometem erros críticos que levam a vazamentos de memória, funcionamento instável e bugs difíceis de detectar. Neste artigo, analisaremos quatro categorias de erros mais comuns entre desenvolvedores de nível intermediário.



1. Vazamentos de memória em closures: não apenas [weak self]



O erro mais popular é usar [weak self] sem entender quando isso é realmente necessário. Muitos desenvolvedores colocam weak self em todos os lugares onde há uma closure, o que leva à destruição prematura de objetos. Ou, ao contrário, esquecem dos ciclos de referência forte em lugares não óbvios.



Erro típico: criar uma referência forte a um objeto dentro de uma closure que esse objeto armazena.



class NetworkManager {    var onCompletion: (() -> Void)?        func fetchData() {        // ERRO: a closure captura self fortemente        onCompletion = {            self.updateUI()        }    }        func updateUI() {        print("UI atualizado")    }}


Solução correta: usar [weak self] ou [unowned self] dependendo do tempo de vida dos objetos.



class NetworkManager {    var onCompletion: (() -> Void)?        func fetchData() {        onCompletion = { [weak self] in            guard let self = self else { return }            self.updateUI()        }    }        func updateUI() {        print("UI atualizado")    }}


Nuance avançada: tenha cuidado com [unowned self]. Se o objeto for liberado e a closure for chamada, o aplicativo irá travar. Use unowned apenas quando tiver 100% de certeza de que o objeto sobreviverá à closure.



2. Trabalho incorreto com async/await e atores



Com o surgimento da Structured Concurrency no Swift 5.5, muitos desenvolvedores começaram a usar ativamente async/await, mas esquecem do MainActor e do Sendable. Isso leva a race conditions e à atualização da UI a partir de uma thread em segundo plano.



Erro típico: chamar uma função assíncrona que deve ser executada na thread principal sem especificar explicitamente @MainActor.



class ViewModel: ObservableObject {    @Published var data: [String] = []        // ERRO: a função não está marcada com @MainActor    func loadData() async {        let result = await fetchFromNetwork()        // Isso pode ser executado em uma thread em segundo plano!        self.data = result    }        func fetchFromNetwork() async -> [String] {        try? await Task.sleep(nanoseconds: 1_000_000_000)        return ["Item1", "Item2"]    }}


Solução correta: usar @MainActor para funções que atualizam a UI.



class ViewModel: ObservableObject {    @Published var data: [String] = []        @MainActor // Agora é garantido que será executado na thread principal    func loadData() async {        let result = await fetchFromNetwork()        self.data = result    }        func fetchFromNetwork() async -> [String] {        try? await Task.sleep(nanoseconds: 1_000_000_000)        return ["Item1", "Item2"]    }}


Nuance avançada: não se esqueça de nonisolated e actor. Se você usar atores, todos os métodos públicos são assíncronos por padrão. Isso pode levar a atrasos inesperados se você não planejar o isolamento.



3. Race Conditions em

Blogs

Book Recommendations