Pergunta

Estou criando um aplicativo para iPhone que retire os dados de uma API da Web, incluindo endereços de email. Eu gostaria de exibir uma imagem associada a cada endereço de e -mail nas células da tabela, por isso estou pesquisando o catálogo de endereços por imagens e voltando a um padrão se o endereço de email não estiver no livro. Isso funciona muito bem, mas tenho algumas preocupações:

  • atuação: As receitas que encontrei para procurar um registro de livro de endereços por endereço de e -mail (ou número de telefone) são supostamente bastante lento. A razão para isso é que deve -se iterar em todos os registros de livros de endereços e, para cada um que tenha uma imagem, itera sobre todos os endereços de email para encontrar uma correspondência. Isso pode demorar muito para um grande livro de endereços, é claro.

  • Células da tabela: Então, pensei em reunir todos os endereços de e -mail para os quais preciso encontrar imagens e encontrá -las de uma só vez. Dessa forma, eu itero através do livro apenas uma vez para todos os endereços. Mas isso não funciona bem para as células da tabela, onde cada célula corresponde a um único endereço de email. Eu teria que reunir todas as imagens antes de exibir qualquer célula (potencialmente lenta) ou fazer com que cada célula procure cada imagem enquanto ela carrega (ainda mais lenta, pois eu precisaria iterar o livro para encontrar uma correspondência para cada endereço de e -mail).

  • Pesquisa assíncrona: Então eu pensei em procurá -los em massa, mas assíncrono, usando NSInvocationOperation. Para cada imagem encontrada no endereço de endereço, eu economizaria uma miniatura na caixa de areia do aplicativo. Em seguida, cada célula pode apenas fazer referência a esse arquivo e mostrar o padrão se não existir (porque não está no livro ou ainda não foi encontrado). Se a imagem for encontrada posteriormente na pesquisa assíncrona, na próxima vez que a imagem precisar ser exibida, ela aparecerá repentinamente. Isso pode funcionar bem para a regeneração periódica de imagens (para quando as imagens são alteradas no livro de endereços, por exemplo). Mas então, para qualquer instância do meu aplicativo, uma imagem pode não aparecer por um tempo.

  • Pesquisa de célula de mesa assíncrona: Idealmente, eu usaria algo como Atualização de célula de tabela assíncrona de Markjnet Para atualizar as células da tabela com uma imagem depois de baixar. Mas para que isso funcione, eu teria que girar um NSInvocationOperation trabalho para cada célula como é exibido e se o ícone em cache estiver ausente na caixa de areia. Mas então voltamos a iterar ineficientemente por todo o catálogo de endereços para cada um - e isso pode ser muitos deles se você acabou de baixar um monte de novos endereços de e -mail.

Então, minha pergunta é: como os outros fazem isso? Eu estava brincando com o Tweetie2 e parece que as atualizações exibidas de tabela de tabela de maneira assíncrona. Presumo que esteja enviando uma solicitação HTTP separada para cada imagem necessária. Em caso afirmativo, imagino que pesquisar no livro de endereços local por endereço de e -mail não seja menos eficiente, então talvez seja a melhor abordagem? Só não se preocupe com os problemas de desempenho associados à pesquisa no catálogo de endereços?

Em caso afirmativo, salvar uma imagem de miniatura na caixa de areia está a melhor abordagem para o cache? E se eu quisesse criar um novo trabalho para atualizar todas as miniaturas com alguma alteração no livro de endereços, digamos uma vez por dia, qual é a melhor abordagem para fazê -lo?

Como o resto de vocês resolve esse tipo de problema? Sugestões seriam muito apreciadas!

Foi útil?

Solução

Independentemente de qual estratégia você usa para o cache real de imagens, eu apenas faria uma passagem pelos dados da lista de endereços cada vez que você recebe um lote de endereços de email, se possível. (E sim, eu faria isso de forma assíncrona.)

Crie um nsmutabledictionário que servirá como seu cache na memória para os resultados da pesquisa. Inicialize este dicionário com cada endereço de e -mail do download como uma chave, com um Sentinel como o valor dessa chave (como [NSNull null]).

Em seguida, itera através de cada Abrecordref no livro de endereços, chamando ABRecordCopyValue(record, kABPersonEmailProperty) e percorrer os resultados em cada abmultivalue que é devolvido. Se algum dos endereços de email forem chaves em seu cache, defina [NSNumber numberWithInt:ABRecordGetRecordId(record)] como o valor dessa chave em seu dicionário.

Usando esse dicionário como um índice de pesquisa, você pode obter rapidamente as imagens do AbreCordRefs apenas para os endereços de email que você está exibindo atualmente na sua exibição de tabela, dada a posição de rolagem atual do usuário, conforme sugerido na resposta de Hoopjones. Você pode adicionar um ouvinte de alteração do livro de endereços para invalidar seu cache, acionar outra operação de indexação e, em seguida, atualizar a visualização, se o seu aplicativo precisar de esse nível de "atualização".

Outras dicas

Eu usaria o último método que você listou (pesquisa de célula de tabela assíncrona), mas procurou apenas imagens para os registros atuais que estão sendo exibidos. Eu sobrecarrego os métodos UIScrollViewDelegate para descobrir quando um usuário parou de rolar e, em seguida, só comece a fazer solicitações para as células visíveis atuais.

Algo assim (isso é ligeiramente modificado de um tutorial que encontrei na web que não consigo encontrar agora, peço desculpas por não citar o autor):

- (void)loadContentForVisibleCells
{
    NSArray *cells = [self.table visibleCells];
    [cells retain];
    for (int i = 0; i < [cells count]; i++) 
    { 
        // Go through each cell in the array and call its loadContent method if it responds to it.
        AddressRecordTableCell *addressTableCell = (AddressRecordTableCell *)[[cells objectAtIndex: i] retain];
        [addressTableCell loadImage];
        [addressTableCell release];
        addressTableCell = nil;
    }
    [cells release];
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 
{
    // Method is called when the decelerating comes to a stop.
    // Pass visible cells to the cell loading function. If possible change 
    // scrollView to a pointer to your table cell to avoid compiler warnings
    [self loadContentForVisibleCells]; 
}


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
    if (!decelerate) 
    {
       [self loadContentForVisibleCells]; 
    }
}

Depois de saber quais registros de endereços estão visíveis atualmente, apenas fazer uma pesquisa por esses (provavelmente registros de 5 a 7) será um raio rápido. Depois de pegar a imagem, basta cache -a em um dicionário para que você não precise refazer a solicitação da imagem posteriormente.

Você parece tentar implementar imagens preguiçosas carregando no UitableView. Há um bom exemplo da Apple, estou referindo -o aqui:Imagens de carga preguiçosas no uitableview

Para sua informação, liberei uma biblioteca gratuita, poderosa e fácil para fazer carregamento de imagem assíncrona e cache de arquivo rápido: Objetos gerenciados HJhttp://www.markj.net/asynchronsous-loading-caching-images-iphone-hjobjman/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top