本文參考http://www.tuicool.com/articles/iMNrAf 進(jìn)行了整理
使用場(chǎng)景
UITableViewCell需要加載來(lái)自服務(wù)器的圖片细诸,cell的寬度一定,高度需要根據(jù)加載的圖片動(dòng)態(tài)調(diào)整微王。
難點(diǎn)
需要顯示的圖片來(lái)自服務(wù)器,只有圖片加載完成以后才能知道圖片的高度贾铝。
解決方法
1.圖片異步加載完成以后更新cell的height嘉抓,刷新tableview。
2.采用SDWebImage緩存已經(jīng)加載過(guò)的圖片胜茧。
3.在tableview處于滑動(dòng)狀態(tài)時(shí)不加載圖片,不刷新tableview仇味,tableview停止滑動(dòng)時(shí)觸發(fā)reloadData呻顽。
4.添加清空緩存空能,防止app占用太多的磁盤空間邪铲。
代碼
//_cellHeights:保存所有cell高度的數(shù)組
//deatilContents:tableview的數(shù)據(jù)源
//配置cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *imageIdentifier = [NSString stringWithFormat:@"imageIdentifier_%ld",(long)indexPath.row];
DetailImageCell *imageCell = [tableView dequeueReusableCellWithIdentifier:imageIdentifier];
if (!imageCell) {
imageCell = [[DetailImageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:imageIdentifier];
}
[self configureCell:imageCell atIndexPath:indexPath];
return imageCell;
}
//根據(jù)獲取的image高度設(shè)置cell高度芬位,如果圖片還沒(méi)有加載成功,就先設(shè)置為默認(rèn)圖片带到,所有cell的高度都存在數(shù)組_cellHeights中
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dict = [deatilContents safeObjectAtIndex:indexPath.row];
UIImage *img = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:[dict safeObjectForKey:@"photoUrl"]];
if (!img) {
img = [UIImage imageNamed:@"placeholder"];
}
CGFloat height = [DetailImageCell cellHeightWithImage:img];
[_cellHeights replaceObjectAtIndex:indexPath.row withObject:[NSString stringWithFormat:@"%f",height]];
return [[_cellHeights safeObjectAtIndex:indexPath.row] floatValue];
}
//pragma mark 設(shè)置帶有圖片的cell
-(void)configureCell:(DetailImageCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [deatilContents safeObjectAtIndex:indexPath.row];
NSString *imgURL = [dict safeObjectForKey:@"photoUrl"];
UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:imgURL];
if ( !cachedImage ) {
//如果tableview正在滾動(dòng)/滑動(dòng)就先不加載圖片昧碉,只有處于靜止?fàn)顟B(tài)時(shí)才開(kāi)始加載
if ( !self.tableView.dragging && !self.tableView.decelerating ) {
[self downloadImage:imgURL forIndexPath:indexPath];
}
//在圖片沒(méi)有加載完成之前英染,先用默認(rèn)圖片替代
[cell setImage:[UIImage imageNamed:@"placeholder"] withHeight:[[_cellHeights safeObjectAtIndex:indexPath.row] floatValue]];
} else {
//緩存中拿到了需要加載的圖片直接顯示真實(shí)圖片
[cell setImage:cachedImage withHeight:[[_cellHeights safeObjectAtIndex:indexPath.row] floatValue]];
}
}
//根據(jù)路徑加載圖片,加載完成后進(jìn)行緩存被饿,并刷新tableview
- (void)downloadImage:(NSString *)imageURL forIndexPath:(NSIndexPath *)indexPath
{
weakSelf(weakSelf)
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:imageURL]
options:SDWebImageDownloaderUseNSURLCache
progress:nil
completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
{
[[SDImageCache sharedImageCache] storeImage:image forKey:imageURL toDisk:YES];
[weakSelf performSelectorOnMainThread:@selector(reloadCellAtIndexPath:)
withObject:indexPath waitUntilDone:NO];
}];
}
//pragma mark - Scroll view delegate
// table view 停止拖動(dòng)了四康,刷新tableview開(kāi)始更新
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self loadImageForOnScreenRows];
}
}
// table view 停止?jié)L動(dòng)了
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadImageForOnScreenRows];
}
//節(jié)約性能,只加載當(dāng)前顯示在屏幕上的cell包含的image
- (void)loadImageForOnScreenRows
{
NSArray *visiableIndexPathes = [self.tableView indexPathsForVisibleRows];
for(NSInteger i = 0; i < [visiableIndexPathes count]; i++)
{
NSDictionary *dict = [deatilContents safeObjectAtIndex:i];
NSString *imgURL = [dict safeObjectForKey:@"photoUrl"];
if (imgURL) {
[self downloadImage:imgURL forIndexPath:visiableIndexPathes[i]];
}
}
}
// 但是別認(rèn)為調(diào)用 table view 的 reloadData 效率就不高狭握,回顧下上面的步驟
// reloadData 實(shí)際上就是向代理要行數(shù)闪金,要行高,對(duì)**顯示出來(lái)**的 cell 填充數(shù)據(jù)
-(void)reloadCellAtIndexPath:(NSIndexPath *)indexpath
{
[self.tableView reloadData];
}
//這個(gè)函數(shù)在需要清空磁盤的地方調(diào)用论颅,一般都是類似于“我的”頁(yè)面
-(void)clearDiskCache
{
//獲取當(dāng)前磁盤緩存的大小
self.cacheStr=[NSString stringWithFormat:@"%.2fM",[[SDImageCache sharedImageCache] getSize]/1024.0/1024.0];
[[SDImageCache sharedImageCache] clearDisk];
}