web-dev-qa-db-fra.com

UICollectionview Défilement instable lors du chargement de cellules

J'ai une galerie dans mon application utilisant une UICollectionView. Les cellules ont une taille approximative de 70,70. J'utilise ALAssets de la ALAssetLibrary dans la galerie que j'ai stockée dans une liste. 

J'utilise le modèle habituel pour remplir les cellules:

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

  mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
  mycell.imageView.image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];
  return mycell;
}

Ma galerie défile saccadée. Je ne comprends pas pourquoi c'est. J'ai essayé d'ajouter un NSCache pour mettre en cache les images miniatures (en pensant que la création des images était coûteuse), mais cela n'a pas aidé pour la performance.

Je m'attendrais à ce que l'interface utilisateur soit aussi crémeuse que l'application boursière.

Je soupçonne maintenant que cela peut être quelque chose dans le UICollectionViewCell prepareForReuse qui peut retenir la méthode dequeueReusableCellWithReuseIdentifier mais en utilisant des instruments, je n'ai pas pu le trouver.

Toute autre chose qui peut être la cause de cela? Existe-t-il un moyen "plus rapide" de préparer la UICollectionViewCell ou de la dequeue de manière plus rapide?

31
Avner Barr

Donc, toute personne ayant des problèmes de défilement doit faire ceci

ajoutez ces 2 lignes après votre retrait

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
95
Avner Barr

Je suppose que "choppyness" provient de l'allocation UIImage, et non de la méthode dequeueReusableCellWithReuseIdentifier. J'essaierais de faire l'allocation des images sur un fil de fond pour voir si cela rend les choses un peu plus difficiles.

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
  mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
     // Load image on a non-ui-blocking thread
    UIImage *image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];

    dispatch_sync(dispatch_get_main_queue(), ^(void) {
        // Assign image back on the main thread
        mycell.imageView.image = image;
    });
  });

  return mycell;
}

Plus de détails peuvent être trouvés ici: https://developer.Apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html

19
preynolds

Chargez vos images en utilisant le sendAsynchronousRequest:queue:completionHandler: de NSURLConnection

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    [cell.imageView setImage:[UIImage imageWithData:data]];
}];
8
Beau Hankins

Cochez les sous-vues de clips et opaque dans l'inspecteur d'attributs, puis cochez la case Paging.

2
A.G

J'ai eu des problèmes avec le défilement UICollectionView.

Ce qui a fonctionné (presque) comme un charme pour moi: j'ai rempli les cellules avec des vignettes en png 90x90. Je dis presque parce que le premier parchemin complet n’est pas aussi lisse, mais n’est plus écrasé ...

Dans mon cas, la taille de la cellule est 90x90. 

J'avais beaucoup de formats png originaux auparavant, et c'était très agité quand la taille originale des png était supérieure à ~ 1000x1000 (beaucoup de crashs au premier défilement).

Donc, je sélectionne 90x90 (ou similaire) sur la UICollectionView et affiche les pngs d'origine (peu importe la taille). J'espère que cela aide les autres.

0
Paulo Souto

Si quelqu'un utilise PhImageManager, le fait de désactiver Synchrone a résolu le problème. (deliveryMode = .FastFormat peut également améliorer les performances, mais le compromis est que la vignette sera de qualité inférieure)

    let option = PHImageRequestOptions()
    option.deliveryMode = .Opportunistic
    option.synchronous = false
    PHImageManager().requestImageForAsset(phAsset, targetSize: CGSizeMake(2048, 2048), contentMode: .AspectFit, options: option, resultHandler: { (image, objects) in
        self.imageView.image = image!
    })
0
NoWhereToBeSeen