Uiscrollview lazy loading

I have all iphone images using AssetsLibrary.I pass UIImage object to imageview and display images in scrollview. There are over 200 images in iphone and I have to display all images in scrollview vertically without using paging. It takes a long time to display images as well as memory problems. Is there any code for lazy loading iphone images in scrollview

+3


source to share


4 answers


I've been working on this lately and have checked many code examples on the internet. None of this made lazy loading (despite the demand) or was much more difficult (useless calls and whistles) than I was willing to put up with. Apple WWDC videos for PhotoPicker seem to show lazy loading, but seem to be more focused on splitting pre-cut images, so not much help.

What I ended up with was to load everything at aspectThumbnails

once, since they are small and don't take up as much memory, and then load the view fullScreenImage

on demand from scrollViewDidEndDecelerating

and reload aspectThumbnail

for the off-screen image. The effect is very fluid and visually, the image gets a little rough and then quickly (via loading the background) is replaced with a higher resolution.

Perhaps it could use more refinements - perhaps loading full resolution images for the current page +1 and -1. I didn’t know it yet. Also, I'm not entirely sure how optimal I am using blocks, but I get no errors.

I am calling this from Segue and setting assetsArray

(NSArray from ALAssets) from a method prepareForSegue:

on my root viewController.



//  ScrollViewController.h
#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>

@interface ScrollViewController : UIViewController <UIScrollViewDelegate>

@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (strong, atomic) ALAssetsLibrary* assetLibrary;
@property (nonatomic,strong)NSMutableArray* assetsArray;
@end

      

//ScrollViewController.m

#import "ScrollViewController.h"

@interface ScrollViewController ()

@property (nonatomic,assign) CGSize currentImageSize;
@property (nonatomic, assign)int currentPages;
@property (nonatomic, assign)int currentPageNum;
@property (nonatomic, strong)UIImage* placeHolder;
@end



@implementation ScrollViewController


- (void)viewDidLoad
{
    [super viewDidLoad];

    //self.placeHolder = [UIImage imageNamed:@"loader.jpg"];
    self.scrollView.delegate = self;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (self.assetsArray != nil) {
        self.currentPages = [self.assetsArray count];

        CGSize size = self.scrollView.frame.size;
        int num = self.currentPages;

        self.scrollView.contentSize=CGSizeMake(size.width*num, size.height);

        [self loadThumbnails];

        self.currentPageNum = 0;
        [self loadFullScreenImageByIndex:self.currentPageNum];
    }
}

-(void)loadThumbnails
{
    int pageCount = self.currentPages;
    CGSize size = self.scrollView.frame.size;
    self.scrollView.contentSize=CGSizeMake(size.width*pageCount, size.height);

    for (int i = 0; i < pageCount; i++) {

        ALAsset *asset = [self.assetsArray objectAtIndex:i];//
        CGRect imageViewFrame;

        // x offset is determined by arrayIndex
        imageViewFrame.origin.x = self.scrollView.frame.size.width * i;
        imageViewFrame.origin.y = 0;
        imageViewFrame.size = self.scrollView.frame.size;

        self.currentImageSize = imageViewFrame.size; // THIS IS WRONG

        UIImage *image = [[UIImage alloc] initWithCGImage:asset.aspectRatioThumbnail];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
        imageView.clipsToBounds = YES;
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        imageView.frame = imageViewFrame;
        imageView.tag = i+1;// start tags at 1

        [self.scrollView addSubview:imageView];
    }
}


- (void)viewDidUnload {
    [self setScrollView:nil];
    [super viewDidUnload];
}

- (void)loadFullScreenImageByIndex:(int)index
{
    int arrayIndex = index;
    int tagNumber = index+1;
    ALAsset *asset = [self.assetsArray objectAtIndex:arrayIndex];

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        UIImage *tmpImage = [[UIImage alloc] initWithCGImage:asset.defaultRepresentation.fullScreenImage];

        __strong __typeof__(weakSelf) strongSelf = weakSelf;
        if ([strongSelf.scrollView viewWithTag:tagNumber] != nil){

            dispatch_async(dispatch_get_main_queue(), ^{
                __strong __typeof__(weakSelf) strongSelf = weakSelf;
                if ([strongSelf.scrollView viewWithTag:tagNumber]!= nil){
                    UIImageView * tmpImageView = (UIImageView*)[strongSelf.scrollView viewWithTag:tagNumber];
                    tmpImageView.image = tmpImage;
                }
            });
        }
    });
}

- (void)loadThumbnailImageByIndex:(int)index
{
    int arrayIndex = index;
    int tagNumber = index+1;

    ALAsset *asset = [self.assetsArray objectAtIndex:arrayIndex];//

    __weak typeof(self) weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        UIImage *tmpImage = [[UIImage alloc] initWithCGImage:asset.aspectRatioThumbnail];        
        __strong __typeof__(weakSelf) strongSelf = weakSelf;
        if ([strongSelf.scrollView viewWithTag:tagNumber] != nil){

            dispatch_async(dispatch_get_main_queue(), ^{
                __strong __typeof__(weakSelf) strongSelf = weakSelf;
                if ([strongSelf.scrollView viewWithTag:tagNumber]!= nil){
                    UIImageView * tmpImageView = (UIImageView*)[strongSelf.scrollView viewWithTag:tagNumber];
                    tmpImageView.image = tmpImage;
                }
            });
        }
    });
}

- (void)manageImages
{
    int currentPage = (self.scrollView.contentOffset.x / self.currentImageSize.width);

    if (currentPage != self.currentPageNum){
        [self loadThumbnailImageByIndex:self.currentPageNum]; //pg no longer visible so load thumb
        [self loadFullScreenImageByIndex:currentPage]; // load full
        self.currentPageNum = currentPage;// store
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self manageImages];
}

      

+4


source


You can use GCD block and center send. in the .h file declare it

dispatch_queue_t imageQueue_;

      

Create NSmutableDictionary



@property (nonatomic, strong) NSMutableDictionary *thumbnailsCache;

      

Use below code to show image.

NSString *thumbnailCacheKey = [NSString stringWithFormat:@"cache%d",imageIndex];

    if (![[self.thumbnailsCache allKeys] containsObject:thumbnailCacheKey]) {

        // thumbnail for this row is not found in cache, so get it from remote website
        __block NSData *image = nil;
        dispatch_queue_t imageQueue = dispatch_queue_create("queueForCellImage", NULL);
        dispatch_async(imageQueue, ^{
            NSString *thumbnailURL = [NSString stringWithFormat:@"%@",deal_Class.deal_imageUrl];
            image = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:@"Your URL"]];
            dispatch_async(dispatch_get_main_queue(), ^{



              imageView.image = [UIImage imageWithData:image];

                if (image) {
                    [self.thumbnailsCache setObject:image forKey:thumbnailCacheKey];
                }


            });
        });

     //   dispatch_release(imageQueue);


    } else {

        // thumbnail is in cache
        NSData *image = [self.thumbnailsCache objectForKey:thumbnailCacheKey];
        dispatch_async(dispatch_get_main_queue(), ^{
            imageview.image = [UIImage imageWithData:image];
        });
    }

      

+1


source


There are many tutorials available for this.

Let me point out some of them:

How to use UIScrollView to scroll and scale content

Scroll Lazy Load Load for iOS

If you have no problem using some DMLazyScrollView code
: Lazy Loading UIScrollView (with infinite page scrolling)

+1


source


You only had to upload the images on the current page plus one or two in either direction. Load images only when you need them, keeping the bounded buffer and deleting images after they leave the buffer. For example, if images 3 and 4 are on screen, images 1, 2, 5 and 6 must be loaded. When the user scrolls through images 5 and 6 on the screen, they will load images 3 and 4, delete 1 and 2 from their memory, and load 7 and 8 to create a new buffer.

0


source







All Articles