UICollectionView scrolling is slow

后端 未结 3 1777
北恋
北恋 2020-12-25 08:43

I have just created a UICollectionView in which The user can add images from their phone to the photo album feature in the app. I have the images save to the a

相关标签:
3条回答
  • 2020-12-25 09:18

    So After some messing around, I've figured out that the problem was based on a few factors.

    One- The images for the thumbnails were too big, so what I did was made a seperate array of images with smaller image sizes that would fit the cell. Two- With the help from @ggrana, opening a seperate thread sped up the process to and made it less laggy. Three- I also found that having an array of images rather than image locations was faster-- only problem is it takes up more memory.

    0 讨论(0)
  • 2020-12-25 09:23

    You will need to make a approach like the one you need to do in the tableviews, you will need to reuse the views, like you reuse yours cells in table view.

    A really good tutorial is this one from Ray Wenderlich:

    In the first part you have the basic, in the second one they talk about the reusable views, you, take a look at the link:

    http://www.raywenderlich.com/22417/beginning-uicollectionview-in-ios-6-part-22

    Edit

    Example to load images async:

    Create at your cell a method loadImageFromFile for example, that receives the path you will cal it this way:

    [cell loadImageFromFile:[recipePhotos objectAtIndex:index]];
    

    And then will look like (maybe you need to adapt something ...):

    - (void) loadImageFromFile:(NSString*)path{
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
            NSData *data= [NSData dataWithContentsOfFile:path];
            UIImage *theImage=[UIImage imageWithData:data];
    
            dispatch_async(dispatch_get_main_queue(), ^{
                cell.imageView.image=theImage;
        });
    });
    
    0 讨论(0)
  • 2020-12-25 09:27

    @ggrana has the right idea. Loading async will definitely help. However, you're still doing redundant work if you load from file every time. One thing to consider would be augmenting the async loading with an NSCache. It's basically an NSDictionary but does memory management itself and dumps data when there is memory pressure.

    So if you have the memory budget, you can actually make your thumbnails on the fly (so you don't have to hard code a size) and store them in the cache. That way your the images only pop in the first time. Every time after that, they load instantly.

    You can use it like so:

    @implementation ...
    {
        NSCache * _johnny;  // get it?
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        [cell setImage:nil]; // since they are reused, prevents showing an old image
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
             UIImage * sticker = [self thumbnailOfSize:CGSizeMake(desiredImageWidth, desiredImageHeight) 
                                              forIndex:[indexPath row]];
             dispatch_async(dispatch_get_main_queue(), ^{
                 [cell setImage:sticker];
             });
        });
    }
    
    // load image from disk and cache thumbnail version
    - (UIImage*) thumbnailOfSize:(CGSize)size forIndex:(NSInteger)index
    {
        NSString * cacheKey = [NSString stringWithFormat:@"%@ %d", NSStringFromCGSize(size), index];
        UIImage * image = [_johnny objectForKey:cacheKey];
    
        if (!image) {
            image = [UIImage imageWithContentsOfFile:_imagePaths[index]];
    
            float desiredWidth = size.width;
            float desiredHeight = size.height;
            float actualHeight = image.size.height;
            float actualWidth = image.size.width;
            float imgRatio = actualWidth / actualHeight;
            float maxRatio = desiredWidth / desiredHeight;
    
            if(imgRatio != maxRatio) {
                if(imgRatio < maxRatio) {
                    imgRatio = desiredHeight / actualHeight;
                    actualWidth = imgRatio * actualWidth;
                    actualHeight = desiredHeight;
                } else {
                    imgRatio = desiredWidth / actualWidth;
                    actualHeight = imgRatio * actualHeight;
                    actualWidth = desiredWidth;
                }
            }
    
            CGRect rect = CGRectMake(0.0, 0.0, actualWidth, actualHeight);
            UIGraphicsBeginImageContextWithOptions(rect.size, FALSE, 0); // do right thing for retina
            [image drawInRect:rect];
            image = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
    
            // here's johnny
            [_johnny setObject:image forKey:cacheKey];
        }
    
        return image;
    }
    
    0 讨论(0)
提交回复
热议问题