28 Mar, 2011 17:54
Cache de recursos carregados da Internet
A solução que apresento aqui é relativamente simples, mas eficaz para gravar qualquer dado proveniente de um endereço na Internet e ainda possui a capacidade de administrar o cache antigo para evitar um armazenamento desnecessário de dados.
Cache Manager
A classe batizada de CacheManager possui 3 métodos principais:
- - (void)gravarCache:(NSData *)data doEndereco:(NSString *)endereco que permite gravar um NSData e associá-lo a um endereço qualquer;
- - (NSData *)cacheDoEndereco:(NSString *)endereco para recuperar o NSData associado previamente ao endereço dado;
- - (void)limparCacheAntigo para apagar quaisquer arquivos de cache mais antigos que MAXIMA_IDADE_CACHE (em segundos).
CacheManager é um singleton definido utilizando a técnica descrita no excelente Cocoa with Love. Para obter uma instância de CacheManager, basta chamar:
[CacheManager sharedCacheManager]
Exemplo de uso
O post que eu escrevi sobre carregamento de imagens da Internet é uma boa base para aplicarmos o CacheManager. Veja como funcionava o método principal da classe UIImageViewRemota:
- (void)carregaImagemEmBackground {
// carrega os dados da imagem
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:enderecoImagem]];
UIImage *imagem = [[UIImage alloc] initWithData:data];
[self performSelectorOnMainThread:@selector(exibeImagemCarregada:) withObject:imagem waitUntilDone:YES];
[imagem release];
}
Com poucas modificações neste método, podemos torná-lo "cache enabled":
- (void)carregaImagemEmBackground {
// solicita os dados do CacheManager
NSData *data = [[CacheManager sharedCacheManager] cacheDoEndereco:enderecoImagem];
if (!data) {
// somente se não houver cache, fazemos o carregamento remoto
data = [NSData dataWithContentsOfURL:[NSURL URLWithString:enderecoImagem]];
[[CacheManager sharedCacheManager] gravarCache:data doEndereco:enderecoImagem];
}
UIImage *imagem = [[UIImage alloc] initWithData:data];
[self performSelectorOnMainThread:@selector(exibeImagemCarregada:) withObject:imagem waitUntilDone:YES];
[imagem release];
}
Simples, não?
Se você quiser que o aplicativo mantenha apenas o cache mais recente, basta modificar MAXIMA_IDADE_CACHE de acordo e, em qualquer ponto do código do seu aplicativo, rodar:
[[CacheManager sharedCacheManager] limparCacheAntigo];
Instalando
Se você gostou da técnica e pretende usá-la em seu aplicativo, baixe o projeto de exemplo e copie os arquivos CacheManager.h, CacheManager.m e SynthesizeSingleton.h para o seu projeto. Não esqueça de dar seu feedback, qualquer sugestão será benvinda.