UIImageView retardé rendu dans UITableView
-
11-09-2019 - |
Question
Ok, j'ai un UITableView
avec UITableViewCell
s personnalisés contenant chacun un UIImageView
dont les images sont téléchargées de manière asynchrone via un NSURLConnection
. Toutes choses assez standard ...
La question est, lorsque les rouleaux de table, les nouvelles images sont téléchargées en arrière-plan correctement mais pas RENDUE jusqu'à ce que la table ne bouge plus.
Comment puis-je obtenir la table pour rendre son contenu même quand il bouge? Merci.
- MISE À JOUR -
Après un examen plus attentif, je trouve que les méthodes de délégués de NSURLConnection
ne sont pas tirer jusqu'à ce que la table cesse de défiler. Pas certain de pourquoi. Toute aide serait grande.
La solution
La raison pour laquelle les messages des délégués de connexion ne se déclenchent pas jusqu'à ce que vous arrêtez le défilement est parce que pendant le défilement, la boucle d'exécution est en UITrackingRunLoopMode
. Par défaut, les horaires de NSURLConnection
lui-même dans NSDefaultRunLoopMode
seulement, de sorte que vous ne recevez pas de messages pendant le défilement.
Voici comment planifier la connexion dans les modes « communs », qui comprend UITrackingRunLoopMode
:
NSURLRequest *request = ...
NSURLConnection *connection = [[NSURLConnection alloc]
initWithRequest:request
delegate:self
startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSRunLoopCommonModes];
[connection start];
Notez que vous devez spécifier startImmediately:NO
dans le initialiseur, qui semble aller à l'encontre de la documentation d'Apple qui suggère que vous pouvez changer de mode de boucle fonctionner même après le démarrage.
Autres conseils
Vous devriez lire sur NSRunLoop. Je soupçonne que, pendant le défilement, la boucle d'exécution est en cours d'exécution dans NSEventTrackingRunLoopMode et le NSURLConnection ne figure pas dans ce mode. Vous pourriez probablement contourner ce problème en appelant scheduleInRunLoop de NSURLConnection. ForMode :, pour que le téléchargement peut se produire pendant le défilement
Cela affectera probablement les performances de défilement, ce qui est probablement la raison du mode boucle d'exécution séparée en premier lieu. Mais l'essayer et voir comment il se sent!
Si vous enveloppez votre image téléchargement et mise à jour dans un NSOperation, les mises à jour se produira comme les rouleaux de table vue.
Un autre avantage de NSOperation, est que vous pouvez annuler l'opération que la cellule glisse hors écran. Il se sentira beaucoup plus sensible à l'utilisateur .. surtout si elles défiler une liste rapidement. Tech-talk d'Apple cette année a encouragé cette technique.
Si vos listes ne sont pas si longtemps, ou vous les préférez continuer à charger, vous pouvez manipuler les priorités de NSOperation à la place.
Tout d'abord ... votre connexion est probablement même pas jusqu'à ce qu'il commence à obtenir de mainRunLoop et c'est là l'animation de défilement est en cours de traitement aussi.
Je suis tombé sur le même problème et fixé en racontant les connexions pour les images de commencer immédiatement lors de la création.
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:wrapper.request delegate:wrapper];
[connection start];
Dans la routine d'achèvement où vous recevez l'image et de définir la cell.imageView.image à l'image reçue, vous devriez vérifier pour voir si cette cellule appartient à l'une des cellules actuellement affichées dans le tableau ... et si alors appelez [tableView reloadData].
NSInteger itemIndex = theIndexInTheRowDataOfTheCellYouStuffedTheImage
NSArray *indicies = [_tableView indexPathsForVisibleRows];
NSUInteger rows = indicies.count;
if (rows > 0 &&
itemIndex >= ((NSIndexPath *)[indicies objectAtIndex:0]).row &&
itemIndex <= ((NSIndexPath *)[indicies objectAtIndex:rows - 1]).row)
{
[_tableView reloadData];
}