From Evernote: |
iOS 使用SDWebImage在table view載入不同高度圖片 |
前言
剛開始我有種困擾,
我希望用table view的方式載入圖片。
下載方式既是非同步,
每個table view cell還要依據圖片大小來調整高度。
這…這...我一度有打算放棄,
改用scroll view來實作~
困境
但是一想到最基本的scroll view實作方式,
就是在create content時指定好frame的大小及內容來源。
也就是說,如果我有100張圖片,豈不要發100個requests!
網路接口都被我塞爆了,再者高度也無法事先取得阿!
咦~其實有比較高明的作法,
我只載入前後幾張圖,loading總比較輕了吧。
不過通常都實作在有paging的情況下(就是一頁一頁翻的效果)
這沒法子恣意滑來滑去。
那我就取消paging限制讓他滑來滑去阿~
可是問題又來了,
scroll view content一直被我切換的狀況下,
request還是無止境的一直發,圖片load下來的效果讓我很擔憂阿。
實作
我是沒用scroll view下去實作試試看,
著眼的還是table view的特性,
就是user滑動過程,只有看得到的部分才會進行繪製
1 | - (UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath |
這樣可以減輕大部分loading,但是還有圖片高度阿!
很窩心的是stackoverflow上也有類似的提問 ( 連結在此 )
重點就是 以image url為key將圖片高度存起來
然後在設定cell高度的function去判斷
回頭看一下SDWebImage這邊要怎麼用好了。
1 2 3 4 5 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *idxKey = [imageArray objectAtIndex:indexPath.row]; CGFloat height = [[[NSUserDefaults standardUserDefaults] objectForKey:idxKey] floatValue]; return (height < 1) ? 240 : height; } |
回頭看一下SDWebImage這邊要怎麼用好了。
可以到 GitHub 下載,MIT License
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { [cell.imageView setImageWithURL:[NSURL URLWithString:urlKey] placeholderImage:nil completed:^(UIImage *image, NSError *err, SDImageCacheType typ) { [activityIndicator removeFromSuperview]; // save height of an image to some cache [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:image.size.height * 320 / image.size.width] forKey:urlKey]; if ([record containsObject:[NSString stringWithFormat:@"%d",indexPath.row]]) { NSLog(@"index:%d record already have it! curr is %d", indexPath.row, currentLoadingIndexPath.row); } else { //animation effect seems not good enough... //[tableView beginUpdates]; //[tableView reloadRowsAtIndexPaths:@[indexPath] // withRowAnimation:UITableViewRowAnimationFade]; //[tableView endUpdates]; [mainTable reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; [record addObject:[NSString stringWithFormat:@"%d",indexPath.row]]; } }]; return cell; } |
在completed底下寫個block
o 移除activityIndicator。 (這轉圈圈的效果稍後補充一下)
o 把image的高度用url當key記錄起來。
o 建一個array (record)把 完成loading image的indexPath.row給記起來 ,
這樣的用意是為了不希望每次都重畫整個table view。
o 註解掉update特定table cell的原因是我試起來的效果不好。
補充
如果想讓SDWebImage的placeholder放一個轉圈圈的效果,
比較快的作法是把 activityIndicator放在cell.contentView 上面。
1 2 3 4 | __block UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; activityIndicator.center = CGPointMake(160, 120); [cell.contentView insertSubview:activityIndicator atIndex:999]; [activityIndicator startAnimating]; |
不用試cell.imageView了,我花了很多力氣,都沒成功 :(
希望這樣可以順便幫到一些忙~
沒有留言:
張貼留言