我們平常會涉及到很多展示圖片的,SDWebImage是我們常用的圖片加載框架,它非常簡單,基本一行代碼就能顯示圖片
[imageView sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder]
但是在網(wǎng)絡不好的情況下,圖片下載的速度完全跟不上我們滑動的速度,于是有了按需加載
按需加載有兩種方式:
第一種為:視圖出現(xiàn)時就會下載圖片,若是此圖片還未下載成功將此單元格滑出屏幕,會取消滑出圖片的下載轉(zhuǎn)而下載此時出現(xiàn)的單元格的圖片。
第二種為:視圖首次出現(xiàn)、停止拖拽、停止減速時就會下載圖片,若是此圖片還未下載成功將此單元格滑出屏幕,會取消滑出圖片的下載轉(zhuǎn)而下載此時出現(xiàn)的單元格的圖片。
由于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;//占位圖需要,不然網(wǎng)絡很差時可看到顯示錯亂
[self.imageVi sd_cancelCurrentImageLoad];//此方法作用是取消imageView以前關聯(lián)的url的下載
}
這兒模擬常規(guī)加載數(shù)據(jù)
- (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
為了避免加載大圖內(nèi)存暴漲crash,我這兒取消了SDWebImage的內(nèi)存緩存,只在disk緩存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//下面兩行代碼主要是防止加載大分辨率圖片時內(nèi)存暴漲crash
[SDImageCache sharedImageCache].config.shouldCacheImagesInMemory = NO;//緩存圖片不放入內(nèi)存
//sd中可點擊diskCacheReadingOptions跳轉(zhuǎn)到這個屬性,提示設置為NSDataReadingMappedIfSafe可提高性能
[SDImageCache sharedImageCache].config.diskCacheReadingOptions = NSDataReadingMappedIfSafe;
return YES;
}
有時候圖片加載多了會出現(xiàn)內(nèi)存警告,所以還需要在AppDelegate.m中重寫下面的方法,內(nèi)存過高需要清理
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
[[SDWebImageManager sharedManager] cancelAll];
[[SDWebImageManager sharedManager].imageCache clearWithCacheType:SDImageCacheTypeDisk completion:nil];
}
demo當然是不能少的啦,demo中圖片鏈接若是失效可自行裝載幾個圖片url(缺資源找度娘)