UICollectionView scrolling is slow

后端 未结 3 1779
北恋
北恋 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: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;
    }
    

提交回复
热议问题