CGImage / UIImage chargement paresseux sur le thread de l'interface utilisateur provoque stutter
Mon programme affiche un défilement horizontal de la surface carrelée avec UIImageViews de gauche à droite. Le Code s'exécute sur le thread de l'INTERFACE utilisateur de s'assurer que les nouveaux-visible UIImageViews avoir un fraîchement chargés UIImage affecté. Le chargement se passe sur un thread d'arrière-plan.
Tout fonctionne presque bien, sauf qu'il n'y est une bégayer comme chaque image devient visible. Au début, je pensais que mon fond travailleur a été verrouillage quelque chose dans le thread de l'INTERFACE utilisateur. J'ai passé beaucoup de temps à le regarder et finalement réalisé que la UIImage est en train de faire quelque supplément de traitement différée sur le thread d'INTERFACE utilisateur quand il devient visible. Ce qui m'intrigue, c', depuis mon thread de travail a code explicite pour la décompression de données de format JPEG.
De toute façon, sur une intuition, j'ai écrit du code de rendu temporaire contexte graphique sur le thread d'arrière-plan et bien sûr, le bégaiement s'en alla. Le UIImage est maintenant en pré-chargé sur mon thread de travail. So far So good.
Le problème est que ma nouvelle "force de lazy load image" méthode n'est pas fiable. Il provoque des intermittents EXC_BAD_ACCESS. Je n'ai aucune idée de ce que UIImage la réalité derrière les coulisses. C'est peut-être la décompression JPEG données. De toute façon, la méthode est la suivante:
+ (void)forceLazyLoadOfImage: (UIImage*)image
{
CGImageRef imgRef = image.CGImage;
CGFloat currentWidth = CGImageGetWidth(imgRef);
CGFloat currentHeight = CGImageGetHeight(imgRef);
CGRect bounds = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
CGAffineTransform transform = CGAffineTransformIdentity;
CGFloat scaleRatioX = bounds.size.width / currentWidth;
CGFloat scaleRatioY = bounds.size.height / currentHeight;
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextScaleCTM(context, scaleRatioX, -scaleRatioY);
CGContextTranslateCTM(context, 0, -currentHeight);
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, currentWidth, currentHeight), imgRef);
UIGraphicsEndImageContext();
}
Et la EXC_BAD_ACCESS qui se passe sur le CGContextDrawImage ligne. QUESTION 1: Suis-je autorisé à faire cela sur un thread autre que le thread d'INTERFACE utilisateur? QUESTION 2: Quel est le UIImage fait "pré-chargement"? QUESTION 3: Quel est le moyen officiel pour résoudre ce problème?
Merci pour la lecture de tout ce qui, tout conseil serait grandement apprécié!
source d'informationauteur JBx
Vous devez vous connecter pour publier un commentaire.
La
UIGraphics*
méthodes sont conçues pour être appelé depuis le thread principal. Ils sont probablement la source de votre problème.Vous pouvez remplacer
UIGraphicsBeginImageContext()
avec un appel àCGBitmapContextCreate()
; c'est un peu plus impliqué (vous devez créer un espace de couleur, de trouver la bonne taille de la mémoire tampon pour créer et affecter vous-même). LeCG*
méthodes sont beaux à exécuter à partir d'un autre thread.Je ne suis pas sûr de savoir comment vous êtes initialisation UIImage, mais si vous le faites avec
imageNamed:
ouinitWithFile:
alors vous pourriez être en mesure de le forcer à charger par le chargement des données vous-même, puis en appelantinitWithData:
. Le bégaiement est probablement en raison de paresseux fichier I/O, donc l'initialiser avec un objet de données de ne pas donner l'option de lecture à partir d'un fichier.J'ai eu le même problème de bégaiement, avec un peu d'aide j'ai trouvé la solution ici: Non paresseux chargement de l'image dans iOS
Deux choses importantes à mentionner:
-
J'ai posté un exemple de projet ici: SwapTestil a environ la même performance que les Pommes' application Photos pour le chargement, l'affichage des images.
J'ai utilisé @jasamer de SwapTest UIImage catégorie à force de charger mon grand UIImage (environ 3000x2100 px) dans un thread de travail (avec NSOperationQueue). Cela réduit le bégaiement de temps lors de la configuration de l'image dans la UIImageView à une valeur acceptable (environ 0,5 sec sur iPad1).
Ici est SwapTest UIImage catégorie... merci encore @jasamer 🙂
UIImage+ImmediateLoading.h fichier
UIImage+ImmediateLoading.m fichier
Et c'est ainsi que j'ai créer NSOpeationQueue et fixer l'image sur le thread principal...
J'ai eu le même problème, même si j'ai initialisé l'image à l'aide de données. (Je suppose que les données sont chargées paresseusement, trop?) J'ai réussi à forcer le décodage en utilisant les catégories suivantes: