Question

Je crée une application iPhone qui va tirer des données vers le bas à partir d'une API Web, y compris les adresses e-mail. Je voudrais afficher une image associée à chaque adresse e-mail dans les cellules de table, donc je suis à la recherche du carnet d'adresses pour les images et retombant sur un défaut si l'adresse e-mail est pas dans le livre. Cela fonctionne très bien, mais j'ai quelques préoccupations:

  • Performance : Les recettes que j'ai trouvé pour la recherche d'un record du carnet d'adresses par adresse e-mail (ou numéro de téléphone) seraient plutôt lent . La raison est que l'on doit parcourir tous les enregistrements du carnet d'adresses, et pour chacun qui a une image, itérer sur toutes les adresses e-mail pour trouver une correspondance. Cela peut prendre du temps pour un grand carnet d'adresses, bien sûr.

  • Tableau cellules : Je pensais que je déduis toutes les adresses e-mail pour que je dois trouver des images et de les trouver à la fois. De cette façon, j'itérer le livre une seule fois pour toutes les adresses. Mais cela ne fonctionne pas pour les cellules de table, où chaque cellule correspond à une adresse e-mail unique. Je dois soit rassembler toutes les images avant d'afficher toutes les cellules (potentiellement lentes), ou ont chaque cellule rechercher chaque image telle qu'elle charge (encore plus lent, comme je l'aurais besoin de parcourir le livre pour trouver une correspondance pour < em> chaque adresse e-mail ).

  • Recherche Asynchronous : Alors je pensais que je les regarde en vrac, mais de manière asynchrone, en utilisant NSInvocationOperation . Pour chaque image trouvée dans AddressBook, je sauverait une vignette dans le bac à sable de l'application. Ensuite, chaque cellule peut simplement faire référence à ce fichier et montrer la valeur par défaut si elle n'existe pas (parce que ce n'est pas dans le livre ou n'a pas encore été trouvé). Si l'image est ensuite trouvée dans la recherche asynchrone, la prochaine fois que l'image doit être affichée il apparaît soudainement. Cela pourrait bien fonctionner pour la régénération périodique des images (lorsque les images ont été modifiées dans le carnet d'adresses, par exemple). Mais pour un cas donné de mon application, une image peut ne pas apparaître en fait pendant un certain temps.

  • Asynchronous Table cellulaire de recherche : Idéalement, je voudrais utiliser quelque chose comme markjnet mise à jour de cellule de tableau asynchrone de pour mettre à jour les cellules de table avec une image une fois qu'il a été téléchargé. Mais pour que cela fonctionne, je dois essaimer un travail de NSInvocationOperation pour chaque cellule comme il est affiché et si l'icône en cache est manquant dans le bac à sable. Mais nous sommes de retour à itérer inefficacement tout le carnet d'adresses pour chacun et qui peut être beaucoup d'entre eux si vous venez de télécharger un tas de nouvelles adresses e-mail.

Alors, ma question est: Comment les autres le font? Je tripotait Tweetie2, et il semble que il met à jour les cellules de tableau affiché de manière asynchrone. Je suppose qu'il est l'envoi d'une requête HTTP distincte pour chaque image dont il a besoin. Si oui, je pense que la recherche du carnet d'adresses local par adresse e-mail est pas moins efficace, alors peut-être c'est la meilleure approche? Il suffit de ne pas se soucier des problèmes de performance liés à la recherche dans le carnet d'adresses?

Si oui, est l'enregistrement d'une image miniature dans le bac à sable la meilleure approche pour la mise en cache? Et si je voulais créer un nouvel emploi pour mettre à jour toutes les vignettes avec des changements dans le carnet d'adresses disent une fois par jour, ce qui est la meilleure approche pour le faire?

Comment le reste de vous résoudre ce genre de problème? Les suggestions seraient appréciés!

Était-ce utile?

La solution

Quelle que soit la stratégie que vous utilisez pour la mise en cache réelle des images, je ne fait un passage à travers les données du carnet d'adresses à chaque fois que vous obtenez un lot d'adresses e-mail, si possible. (Et oui, je ferais ce de manière asynchrone.)

Créer un NSMutableDictionary qui vous servira de cache en mémoire pour les résultats de recherche. Initialiser ce dictionnaire à chaque adresse e-mail du téléchargement comme une clé, avec une sentinelle comme la valeur de cette clé (comme [NSNull null]).

Ensuite, itérer à travers chaque ABRecordRef du Carnet d'adresses, et appelant ABRecordCopyValue(record, kABPersonEmailProperty) une boucle à travers les résultats dans chaque ABMultiValue qui sont retournés. Si l'une des adresses e-mail sont clés dans votre cache, définissez [NSNumber numberWithInt:ABRecordGetRecordId(record)] la valeur de cette clé dans votre dictionnaire.

L'utilisation de ce dictionnaire comme un index de recherche, vous pouvez obtenir rapidement les images de ABRecordRefs uniquement pour les adresses e-mail que vous affichez actuellement dans votre vue de tableau étant donné la position de défilement actuelle de l'utilisateur, comme suggéré dans la réponse de hoopjones. Vous pouvez ajouter un écouteur de modification du carnet d'adresses pour invalider votre cache, déclencher une autre opération d'indexation, puis mettre à jour la vue, si votre application a besoin de ce niveau de « mise à jour-ness ».

Autres conseils

J'utilise la dernière méthode que vous avez indiqué (Asynchronous Lookup Table cellulaire), mais seulement regarder les images pour les enregistrements en cours en cours d'affichage. Je surcharger les méthodes de UIScrollViewDelegate pour savoir quand un utilisateur a cessé de défiler, puis commencer seulement faire des demandes pour les cellules visibles actuelles.

Quelque chose comme ça (ce qui est légèrement modifié par un tutoriel j'ai trouvé sur le web que je ne trouve pas maintenant, des excuses pour ne pas citer l'auteur):

- (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]; 
    }
}

Une fois que vous savez quels documents sont actuellement visibles adresse, en faisant simplement une recherche pour les personnes (5 à 7 dossiers probablement) seront rapides comme l'éclair. Une fois que vous prenez l'image, juste en cache dans un dictionnaire afin que vous n'avez pas de refaire la demande de l'image plus tard.

Vous semblez essayer de mettre en œuvre des images dans le chargement paresseux UITableView. il y a un bon exemple d'Apple, je fais référence ici: Lazy UITableView

Pour votre information, j'ai publié une bibliothèque libre, puissant et facile pour faire le chargement d'images asynchrone et la mise en cache de fichiers rapide: HJ Managed Objects http://www.markj.net/asynchronous-loading-caching- images-iphone-hjobjman /

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top