我们平常会涉及到很多展示图片的,SDWebImage是我们常用的图片加载框架,它非常简单,基本一行代码就能显示图片
[imageView sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder]
但是在网络不好的情况下,图片下载的速度完全跟不上我们滑动的速度,于是有了按需加载
按需加载有两种方式:
第一种为:视图出现时就会下载图片,若是此图片还未下载成功将此单元格滑出屏幕,会取消滑出图片的下载转而下载此时出现的单元格的图片。
第二种为:视图首次出现、停止拖拽、停止减速时就会下载图片,若是此图片还未下载成功将此单元格滑出屏幕,会取消滑出图片的下载转而下载此时出现的单元格的图片。
由于tableView和collectionView的单元格重用机制,很容易造成图片未下载完显示错乱,所以需要在自定义cell中重写prepareForReuse方法,下面的imageVi为自定义UIImageView控件
vc.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HKTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kTableViewCellId forIndexPath:indexPath];
cell.placeholderImage = self.placeholderImage;
PersonModel *model = self.dataArr[indexPath.row];
if (self.segmentControl.selectedSegmentIndex == 0) {//第一种
cell.tableView = tableView;
cell.indexPath = indexPath;
cell.model = model;
} else {//第二种
cell.titleLabel.text = model.name;
cell.imageVi.image = self.placeholderImage;
UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:model.picture];
if (cacheImage) {
NSLog(@"图片尺寸%@",NSStringFromCGSize(cacheImage.size));
cell.imageVi.image = cacheImage;
} else {
if (!tableView.isDragging && !tableView.isDecelerating) {
[cell.imageVi sd_setImageWithURL:[NSURL URLWithString:model.picture] placeholderImage:self.placeholderImage completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
image = [image drawImageWithSize:CGSizeMake(kSCREEN_WIDTH, 600)];
cell.imageVi.image = image;
[[SDImageCache sharedImageCache] storeImage:image forKey:model.picture completion:nil];
}];
}
}
}
return cell;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
if (self.segmentControl.selectedSegmentIndex == 1) {//适用于第二种
[self loadImageForCellRows];
}
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
if (self.segmentControl.selectedSegmentIndex == 1) {//适用于第二种
[self loadImageForCellRows];
}
}
#pragma mark - 加载图片
- (void)loadImageForCellRows {
NSArray *cells = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath * indexPath in cells) {
HKTableViewCell *cell = (HKTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:self.dataArr[indexPath.row]];
if (cacheImage) {
cell.imageVi.image = cacheImage;
} else {
[cell.imageVi sd_setImageWithURL:[NSURL URLWithString:self.dataArr[indexPath.row]] placeholderImage:[UIImage imageNamed:@"placeholder"]];
}
}
}
cell.m
- (void)prepareForReuse {
[super prepareForReuse];
self.imageVi.image = self.placeholderImage;//占位图需要,不然网络很差时可看到显示错乱
[self.imageVi sd_cancelCurrentImageLoad];//此方法作用是取消imageView以前关联的url的下载
}
这儿模拟常规加载数据
- (void)setModel:(PersonModel *)model {
_model = model;
if (self.tableView && self.indexPath) {
self.titleLabel.text = model.name;
UIImage *cacheImage = [[SDImageCache sharedImageCache] imageFromCacheForKey:model.picture];
if (cacheImage) {
self.imageVi.image = cacheImage;
NSLog(@"图片尺寸%@",NSStringFromCGSize(cacheImage.size));
} else {
NSArray *cells = [self.tableView indexPathsForVisibleRows];
if ([cells containsObject:self.indexPath]) {
[self.imageVi sd_setImageWithURL:[NSURL URLWithString:model.picture] placeholderImage:self.placeholderImage completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
image = [image drawImageWithSize:CGSizeMake(kSCREEN_WIDTH, 600)];
self.imageVi.image = image;
[[SDImageCache sharedImageCache] storeImage:image forKey:model.picture completion:nil];
}];
}
}
}
}
AppDelegate.m
为了避免加载大图内存暴涨crash,我这儿取消了SDWebImage的内存缓存,只在disk缓存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//下面两行代码主要是防止加载大分辨率图片时内存暴涨crash
[SDImageCache sharedImageCache].config.shouldCacheImagesInMemory = NO;//缓存图片不放入内存
//sd中可点击diskCacheReadingOptions跳转到这个属性,提示设置为NSDataReadingMappedIfSafe可提高性能
[SDImageCache sharedImageCache].config.diskCacheReadingOptions = NSDataReadingMappedIfSafe;
return YES;
}
有时候图片加载多了会出现内存警告,所以还需要在AppDelegate.m中重写下面的方法,内存过高需要清理
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[SDWebImageManager sharedManager] cancelAll];
[[SDWebImageManager sharedManager].imageCache clearWithCacheType:SDImageCacheTypeDisk completion:nil];
}
demo当然是不能少的啦,demo中图片链接若是失效可自行装载几个图片url(缺资源找度娘)