Pauvres UICollectionView Les Performances De Défilement Avec UIImage
J'ai un UICollectionView dans mon application, et chaque cellule est une UIImageView et certaines étiquettes de texte. Le problème est que lorsque j'ai le UIImageViews l'affichage de leurs images, les performances de défilement est terrible. C'est loin d'être aussi lisse que le défilement de l'expérience d'un UITableView ou même le même UICollectionView sans UIImageView.
J'ai trouvé cette question à partir d'un il ya quelques mois, et il semble que la réponse a été trouvée, mais il est écrit en RubyMotion, et je ne comprends pas. J'ai essayé de voir comment le convertir à Xcode, mais depuis je n'ai jamais utilisé NSCache soit, c'est un peu dur pour. L'affiche il y a également souligné ici sur la mise en œuvre de quelque chose en plus de leur solution, mais je ne sais pas où mettre ce code soit. Peut-être parce que je ne comprends pas le code de la première question.
Quelqu'un pour être en mesure d'aider à traduire ceci dans Xcode?
def viewDidLoad
...
@images_cache = NSCache.alloc.init
@image_loading_queue = NSOperationQueue.alloc.init
@image_loading_queue.maxConcurrentOperationCount = 3
...
end
def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]
if cached_image = @images_cache.objectForKey(image_path)
cell.image = cached_image
else
@operation = NSBlockOperation.blockOperationWithBlock lambda {
@image = UIImage.imageWithContentsOfFile(image_path)
Dispatch::Queue.main.async do
return unless collectionView.indexPathsForVisibleItems.containsObject(index_path)
@images_cache.setObject(@image, forKey: image_path)
cell = collectionView.cellForItemAtIndexPath(index_path)
cell.image = @image
end
}
@image_loading_queue.addOperation(@operation)
end
end
Voici le code à partir de la deuxième question que le demandeur de la première question dit résolu le problème:
UIImage *productImage = [[UIImage alloc] initWithContentsOfFile:path];
CGSize imageSize = productImage.size;
UIGraphicsBeginImageContext(imageSize);
[productImage drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
productImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Encore une fois, je ne suis pas sûr de savoir comment/où à la mettre en œuvre.
Merci beaucoup.
- Poster votre code! Qu'avez-vous essayé? Pourquoi les performances de votre application lent? Quel est le résultat de profilage pour voir ce qu'il se passe?
- Ce n'est pas la totalité de mon application qui est d'avoir de lenteur, c'est seulement le défilement à travers les cellules de la UICollectionView. Le reste de l'appli fonctionne très bien. Je suis actuellement à l'aide
cell.cardImageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:tempCard]];
de régler l'image. L'image utilisée(s) ne fait pas partie de l'app bundle, mais généralement téléchargés et stockés dans les Caches dossier.
Vous devez vous connecter pour publier un commentaire.
Voici le modèle que j'ai suivi. Toujours charger asynch et de mettre en cache le résultat. Ne font aucune hypothèse sur l'état de la vue lorsque l'asynch charge de finitions. J'ai une classe qui simplifie les charges comme suit:
Maintenant la cellule (collection ou un tableau) mise à jour est assez simple:
url
est toujours à venirnil
. Toute pensée?NSURL
au point de l'app store localement.url
être nul. J'ai été en utilisant un chemin plutôt que url. Essentiellement, j'ai été absent de lafile://
partie de la chaîne. Je suis maintenant en mesure de voir l'intégralité de l'URL qui est généré, mais c'est toujours pas le chargement de l'image. Quand j'ai mis l'URL dans Safari sur mon ordinateur, il charge l'image parfaitement, donc je sais que l'URL est valide. Cependant, le chargement d'une image à partir de mon serveur plutôt que localement fonctionne, et le scrolling est étonnamment lisse. En suivant les étapes, à la fois locaux et distants Url comportent de la même façon, donc je ne sais pas où est la question.Cache.db
fichier. Il me semble qu'il n'en garder une copie locale de l'image quelque part parce que, après l'exécution de l'application une fois, il ne retourna jamais à- (void)startWithCompletion:(void (^)(UIImage *, NSError *))completion
UICollectionView
défile aussi bien avec les images comme il le fait sans. Merci beaucoup!if (image) return completion(image, nil);
. La ligne renvoie uneblock
à l'intérieur d'unvoid
méthode, quelle est donc lablock
étant retourné?En général mauvais comportement de défilement pour UICollectionViews ou UITableViews se produit parce que les cellules sont retirés et construit dans le thread principal par iOS. Il y a peu de liberté de cellules préalablement mis en cache ou de les construire dans un thread d'arrière-plan, au lieu de cela, ils sont retirés et construit comme vous le faites défiler le blocage de l'INTERFACE utilisateur. (Personnellement, je trouve cette mauvaise conception par Apple tous si elle n'simplifier les choses, parce que vous n'avez pas à être au courant au sujet de potentiels problèmes de threading. Je pense qu'ils devraient avoir donné un crochet bien que de fournir une implémentation personnalisée pour un UICollectionViewCell/UITableViewCell piscine qui peut gérer la file d'attente, de réutiliser des cellules).
Les causes les plus importantes pour diminuer les performances sont en effet liées à des données de l'image (dans l'ordre décroissant) sont en mon expérience:
Parce que je suis très pointilleux sur la lisse de défilement (même si c'est seulement la première fois qu'une cellule est utilisé) j'ai construit un cadre préalablement mis en cache par les cellules sous-classement UINib (ce qui est essentiellement le seul crochet que vous obtenez dans la file d'attente des processus utilisés par iOS). Mais peut-être au-delà de vos besoins.
J'ai eu des questions à propos de
UICollectionView
de défilement.Ce qui a fonctionné (presque) comme un charme pour moi: j'ai renseigné les cellules avec des vignettes au format png 90x90. Je dis "presque" parce que le premier complet de défilement n'est pas si lisse, mais jamais écrasé plus.
Dans mon cas, la taille de la cellule est 90x90.
J'ai eu beaucoup de png d'origine tailles avant, et c'était très agitée quand png taille d'origine était supérieure à ~1000x1000 (nombreux accidents sur le premier parchemin).
Donc, je sélectionne 90x90 (ou similaire) sur le
UICollectionView
et afficher l'original de la png (peu importe la taille). espérons qu'il peut aider d'autres personnes.