Uiscrollview延迟加载
我已经有了使用AssetsLibrary的iPhone的所有图像。我在ImageView中传递UIImage对象,并显示滚动视图中的图像。 在iphone中有超过200个图像,我必须垂直显示所有的图像滚动视图不使用分页。这需要大量的时间来显示图像,它也有内存问题。 有没有在滚动视图中延迟加载iphone图像的任何代码
最近我一直在做这个工作,并且在网上检查了大量的示例代码。 没有一个是真正的懒惰加载(尽pipe声称)或更复杂(不必要的钟声和哨声)比我愿意忍受。 PhotoPicker的Apple WWDCvideo显示延迟加载,但似乎更侧重于预先切片图像的平铺,所以没有太多的帮助。
我最终做的是一次加载所有的aspectThumbnails
,因为它们很小,不占用那么多的内存,然后根据需要从scrollViewDidEndDecelerating
加载fullScreenImage
表示,并重新加载aspectThumbnail
去屏幕外。 效果非常stream畅和直观,图像稍微粗糙,然后快速(通过背景加载)replace为更高分辨率的图像。
它可能会使用更多的细化 – 也许加载当前页面+1和-1的全分辨率图像。 到目前为止,我还没有做到这一点。 另外,我并不完全确定我是否使用了最优化的模块,但没有发现错误。
我从一个Segue中调用它,并在我的根viewController的prepareForSegue:
方法中设置assetsArray
( assetsArray
NSArray)。
// 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_;
创build一个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]; }); }
有很多教程可用于此。
让我指出其中的一些:
如何使用UIScrollView来滚动和放大内容
为iOS拖动“懒惰图片加载”
如果您在使用某人的代码时没有问题
DMLazyScrollView:延迟加载UIScrollView(无限页面滚动)
您应该只在当前页面加载了一个或两个图像。 只在需要时加载图像,保留有限的缓冲区,并在离开缓冲区后删除图像。 例如,如果图像3和4在屏幕上,则应该加载图像1,2,5和6。 当用户滚动屏幕上的图像5和6时,它将保持加载图像3和4,将其内存中的1和2删除,并将加载7和8来创build新的缓冲区。