3

我已经使用 AssetsLibrary 获得了 iphone 的所有图像。我在 imageview 中传递 UIImage 对象并在滚动视图中显示图像。iphone 中有 200 多张图像,我必须在不使用分页的情况下垂直显示滚动视图中的所有图像。这需要大量时间来显示图像,并且还存在内存问题。是否有任何代码用于在滚动视图中延迟加载 iphone 图像

4

4 回答 4

4

我最近一直在研究这个,并在网上查看了大量的示例代码。没有一个真正做到延迟加载(尽管声称)或具有比我愿意忍受的更复杂(不必要的花里胡哨)。PhotoPicker 的 Apple WWDC 视频似乎显示延迟加载,但似乎更专注于预切片图像的平铺,因此没有太大帮助。

我最终做的是aspectThumbnails一次加载所有内容,因为它们很小并且不占用太多内存,然后fullScreenImage按需加载表示scrollViewDidEndDecelerating并重新加载aspectThumbnail图像视图离开屏幕。效果非常流畅和视觉上,图像有点粗糙,然后很快(通过背景加载)被更高分辨率的图像替换。

它可能可以使用更多的细化 - 可能为 currentPage +1 和 -1 加载全分辨率图像。我还没有解决这个问题。此外,我不完全确定我对块的使用是否处于最佳状态——但没有出错。

我从 Segue 调用它,并在我的根 viewController 上assetsArray的方法中设置 (NSArray of ALAssets) 。prepareForSegue:

//  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];
}
于 2013-02-02T11:37:22.563 回答
1

您可以使用 GCD 块和大型中央调度。在你的 .h 文件中声明它

dispatch_queue_t imageQueue_;

创建一个 NSmutableDictionary

@property (nonatomic, strong) NSMutableDictionary *thumbnailsCache;

使用下面的代码显示图像。

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];
        });
    }
于 2013-02-02T08:41:07.857 回答
1

有很多可用的教程。

让我指出其中的一些:

如何使用 UIScrollView 滚动和缩放内容

iOS 的滚动延迟图像加载

如果您在使用某人的代码
DMLazyScrollView 时没有问题:延迟加载 UIScrollView(无限页面滚动)

于 2013-02-02T11:54:52.503 回答
0

您应该只加载当前页面上的图像加上任一方向的一个或两个。仅在需要时加载图像,保留有限的缓冲区,并在图像离开缓冲区后删除图像。例如,如果图像 3 和 4 在屏幕上,则应加载图像 1、2、5 和 6。当用户滚动以使图像 5 和 6 出现在屏幕上时,它将保持图像 3 和 4 的加载,将从内存中删除 1 和 2,并加载 7 和 8 以创建新的缓冲区。

于 2013-02-02T07:26:04.267 回答