我已经使用 AssetsLibrary 获得了 iphone 的所有图像。我在 imageview 中传递 UIImage 对象并在滚动视图中显示图像。iphone 中有 200 多张图像,我必须在不使用分页的情况下垂直显示滚动视图中的所有图像。这需要大量时间来显示图像,并且还存在内存问题。是否有任何代码用于在滚动视图中延迟加载 iphone 图像
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];
}
您可以使用 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];
});
}
您应该只加载当前页面上的图像加上任一方向的一个或两个。仅在需要时加载图像,保留有限的缓冲区,并在图像离开缓冲区后删除图像。例如,如果图像 3 和 4 在屏幕上,则应加载图像 1、2、5 和 6。当用户滚动以使图像 5 和 6 出现在屏幕上时,它将保持图像 3 和 4 的加载,将从内存中删除 1 和 2,并加载 7 和 8 以创建新的缓冲区。