Otimização de desempenho de aplicativos Swift para iniciantes

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
```html

Introdução: por que o desempenho é importante desde o primeiro dia



Quando você começa a programar em Swift, é fácil focar apenas na funcionalidade: "só precisa funcionar". No entanto, desenvolvedores experientes sabem: otimização de desempenho não é um toque final, mas uma base que é construída desde as primeiras linhas de código. Um aplicativo lento perde usuários, drena a bateria e recebe avaliações negativas.



Neste artigo, vamos abordar os principais aspectos da otimização de aplicativos Swift para iOS e macOS. Você aprenderá como evitar erros comuns de iniciantes, trabalhar com memória, threads e profiling. Cada seção contém exemplos práticos de código que você pode aplicar imediatamente em seus projetos.



1. Gerenciamento de memória: ARC e como evitar retain cycles



Swift usa Automatic Reference Counting (ARC) para gerenciar memória. Isso significa que os objetos são liberados quando não há mais referências fortes para eles. Mas se você criar uma referência cíclica (retain cycle), a memória nunca será liberada — ocorrerá um vazamento.



Referências fracas e não proprietárias

Use weak e unowned para quebrar os ciclos. Isso é mais frequentemente necessário em closures e delegates.



class ViewController: UIViewController {    var networkManager: NetworkManager?        func fetchData() {        networkManager?.fetch { [weak self] result in            guard let self = self else { return }            // Processamento do resultado            self.updateUI(with: result)        }    }}


Quando usar:

  • weak — se a referência pode se tornar nil (por exemplo, delegate).
  • unowned — se você tem certeza de que o objeto viverá mais que a closure (por exemplo, controlador pai).


Evite cópias desnecessárias

Value types (structs, enums) são copiados na atribuição. Para dados grandes, use class ou passe por referência com inout.



// Ruim: cópia de um array grandefunc processLargeArray(_ array: [Int]) {    // array é uma cópia}

// Bom: passagem por referênciafunc processLargeArray(_ array: inout [Int]) { // array é uma referência ao original}


2. Trabalhando com multithreading: GCD e async/await



iOS e macOS são sistemas multithread. Se você executa operações pesadas (carregamento de dados, processamento de imagens) na thread principal, a interface "congela". Use Grand Central Dispatch (GCD) ou o moderno async/await.



GCD: padrões básicos

DispatchQueue.global(qos: .userInitiated).async {    // Trabalho pesado em segundo plano    let result = performHeavyCalculation()        DispatchQueue.main.async {        // Atualização da UI na thread principal        self.label.text = "\\(result)"    }}


QoS (Quality of Service):

  • .userInteractive — para UI (quase instantâneo).
  • .userInitiated — para ações do usuário (segundos).
  • .utility — para tarefas longas (barras de progresso).
  • .background — para sincronização em segundo plano (não urgente).


Async/await (Swift 5.5+)

Uma forma mais legível de trabalhar com assincronia:

func fetchImage(from url: URL) async throws -> UIImage {    let (data, _) = try await URLSession.shared.data(from: url)    guard let image = UIImage(data: data) else {        throw URLError(.badServerResponse)    }    return image}

// Chamada em TaskTask { do { let image = try await fetchImage(from: url) self.imageView.image = image } catch { print("Erro ao carregar: \\(er") ```

Blogs

Book Recommendations