Introdução: por que essa pergunta é tão popular?
\n\nTodo mundo que já escreveu um aplicativo para iOS já se deparou com a tarefa: "Como exibir uma imagem da internet no meu aplicativo?" No Stack Overflow, a pergunta "Loading/Downloading image from URL on Swift" acumulou milhares de visualizações e centenas de respostas. Por quê? Porque é a base com a qual se começa a trabalhar com rede no iOS. E embora pareça simples — pegar a URL, baixar os dados, exibir — na prática, os desenvolvedores enfrentam várias armadilhas: bloqueio da thread principal, vazamentos de memória, falta de cache e lentidão.
\n\nNeste artigo, vamos analisar todas as formas populares de carregar imagens de URL em Swift, responder a perguntas frequentes e mostrar exemplos de código que podem ser usados imediatamente em seu projeto.
\n\n1. A maneira mais simples: URLSession + Data
\n\nVamos começar com o clássico. Em Swift, para baixar dados pela rede, usamos URLSession. Aqui está o código funcional mínimo:
import UIKit\n\nfunc loadImage(from urlString: String, completion: @escaping (UIImage?) -> Void) {\n guard let url = URL(string: urlString) else {\n completion(nil)\n return\n }\n \n URLSession.shared.dataTask(with: url) { data, response, error in\n guard let data = data, error == nil else {\n completion(nil)\n return\n }\n let image = UIImage(data: data)\n DispatchQueue.main.async {\n completion(image)\n }\n }.resume()\n}\n\n\nImportante: passamos o resultado para a thread principal através de DispatchQueue.main.async. Se não fizermos isso, corremos o risco de um crash ao tentar atualizar a UI a partir de uma thread em segundo plano.
Como usar:
\n\nloadImage(from: "https://example.com/image.jpg") { image in\n self.imageView.image = image\n}\n\n\nEste método é adequado para projetos simples, quando você precisa carregar 1-2 imagens. Mas para aplicativos reais, não é ideal: não há cache, não há tratamento de erros e, ao rolar uma tabela, tudo ficará lento.
\n\n2. Abordagem moderna: async/await (Swift 5.5+)
\n\nA partir do iOS 15 e Swift 5.5, tornou-se possível escrever código assíncrono em estilo imperativo com async/await. O carregamento de imagens torna-se elegante e legível:
import UIKit\n\nfunc loadImageAsync(from urlString: String) async throws -> UIImage? {\n guard let url = URL(string: urlString) else {\n throw URLError(.badURL)\n }\n \n let (data, _) = try await URLSession.shared.data(from: url)\n return UIImage(data: data)\n}\n\n\nUso em SwiftUI:
\n\nstruct ContentView: View {\n @State private var image: UIImage?\n \n var body: some View {\n VStack {\n if let image = image {\n Image(uiImage: image)\n .resizable()\n .scaledToFit()\n } else {\n ProgressView()\n }\n }\n .task {\n do {\n image = try await loadImageAsync(from: "https://example.com/image.jpg")\n } catch {\n print("Erro de carregamento: \\(error)")\n }\n }\n }\n}\n\n\nPor que isso é legal? O código tornou-se linear, sem closures aninhados, e é fácil de ler. No entanto, o problema do cache permanece — ainda baixamos a imagem do zero toda vez.
\n\n3. Cache: como não consumir o tráfego do usuário
\n\nA pergunta mais frequente que os iniciantes fazem é: "Por que minhas imagens são baixadas toda vez que rolo a tabela?" A resposta é simples — você não está usando cache.
\n\nNo iOS, existe o URLCache embutido, que pode ser configurado para URLSession. Mas para imagens, é melhor usar NSCache — ele automá