Introdução: Por que o cache é a chave para o desempenho de aplicações Swift
No desenvolvimento moderno em Swift, seja para uma aplicação iOS ou uma solução servidor com Vapor, a velocidade e a capacidade de resposta da interface dependem diretamente de um gerenciamento eficiente de dados. O cache não é apenas "memorizar" resultados, mas toda uma ciência sobre como reduzir o tempo de acesso aos dados, diminuir a carga na rede e no banco de dados, e garantir um funcionamento suave mesmo sob picos de carga.
Em nível avançado, os desenvolvedores Swift enfrentam a escolha: usar mecanismos integrados (NSCache, URLCache) ou conectar sistemas externos como Redis e Memcached. Cada uma dessas ferramentas tem sua própria arquitetura e área de aplicação. Neste artigo, vamos analisar como integrar e combinar essas soluções de forma eficaz no ecossistema Swift.
1. Soluções integradas: NSCache e URLCache
1.1 NSCache — cache leve para objetos
NSCache é um dicionário thread-safe integrado ao Foundation. Ele é ideal para armazenar em cache objetos que são caros de criar ou carregar (por exemplo, imagens, resultados de cálculos complexos). A principal vantagem é a limpeza automática quando há falta de memória, o que é crítico para aplicações móveis.
import Foundation
final class ImageCache { static let shared = ImageCache() private let cache = NSCache<NSString, UIImage>() private init() { cache.countLimit = 100 // Máximo de 100 objetos cache.totalCostLimit = 50 * 1024 * 1024 // 50 MB } func getImage(for key: String) -> UIImage? { return cache.object(forKey: key as NSString) } func setImage(_ image: UIImage, for key: String, cost: Int? = nil) { if let cost = cost { cache.setObject(image, forKey: key as NSString, cost: cost) } else { cache.setObject(image, forKey: key as NSString) } } func removeImage(for key: String) { cache.removeObject(forKey: key as NSString) } func clearAll() { cache.removeAllObjects() }}Nuances importantes:
countLimitetotalCostLimitsão recomendações, não limites rígidos. O sistema decide quando remover objetos.- As chaves devem ser do tipo
NSString, nãoString(Swift faz a ponte automaticamente, mas é melhor converter explicitamente). - Não use
NSCachepara dados grandes que não cabem na memória.
1.2 URLCache — cache de requisições de rede
URLCache é um cache de sistema para requisições HTTP. Ele salva automaticamente as respostas do servidor (considerando os cabeçalhos Cache-Control) e as retorna sem acessar a rede. A configuração permite controlar o volume de memória e disco.
import Foundation
// Configuração do URLCache para toda a aplicaçãolet memoryCapacity = 20 * 1024 * 1024 // 20 MBlet diskCapacity = 100 * 1024 * 1024 // 100 MBlet cache = URLCache(memoryCapacity: memoryCapacity, diskCapacity: diskCapacity, diskPath: "myCache")URLCache.shared = cache
// Exemplo de uso com URLSessionlet config = URLSessionConfiguration.defaultconfig.requestCachePolicy = .returnCacheDataElseLoad // Primeiro cache, depois redeconfig.urlCache = cache
let session = URLSession(configuration: config)let url = URL(string: "https://api.example.com/data")!let task = session.dataTask(with: url) { data, response, error in // Os dados serão obtidos do cache, se existirem e não estiverem desatualizados}task.resume()Dica avançada: Para forçar a atualização do cache, use a política .reloadIgnoringLocalCacheData, e para gerenciamento manual, os métodos cachedResponse(for:) e storeCachedResponse(_:for:).