ios開發(fā)UITableViewCell圖片加載優(yōu)化詳解
前言
我們平時(shí)用UITableView用的很多,所以對(duì)列表的優(yōu)化也是很關(guān)注的。很多時(shí)候,我們?cè)O(shè)置UIImageView,都是比例固定好寬高的,然后通過 scaleAspectFill 和 clipsToBounds 保持圖片不變形,這樣子做開發(fā)的效率是很高的,畢竟圖片寬高我們都是固定好的了。
那如果產(chǎn)品要求圖片按真正的比例展示出來呢?如果服務(wù)器有返回寬和高,那就好辦了,那如果沒有呢,我們應(yīng)該怎么去做呢?
下面就讓我們一起來探索吧。
圖片自適應(yīng)比例
一般我們的做法都是用UITableViewAutomaticDimension來實(shí)現(xiàn)的。
以往的做法,我們都是直接 sd_setImageWithURL 來實(shí)現(xiàn)添加圖片,那現(xiàn)在也一樣,我們也是通過這個(gè)來獲取圖片寬和高。
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDExternalCompletionBlock)completedBlock
完成后,我們可以拿到UIImage,從而知道圖片的 size 。然后我們就可以按比例來獲取圖片的高度,再通過更新約束來改變圖片高度。
大概做法如下:
[_imageView sd_setImageWithURL:[NSURL URLWithString:model.urlStr] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL _Nullable imageURL) {
if (image) {
// 獲取圖片寬高
CGSize imageSize = image.size;
CGFloat maxWidth = kSCREEN_WIDTH - 32;
// 按比例獲取當(dāng)前的高度
CGFloat height = imageSize.height * maxWidth / imageSize.width;
[self.imageView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(height);
}];
}
}];
然后我們一運(yùn)行代碼,發(fā)現(xiàn)圖片的高度并沒有展示我們想要的高度,可以說是連高度都沒有。
很明顯是圖片的高度沒有生效。想想也是,我們是異步調(diào)用加載圖片的,這時(shí)候等異步結(jié)果回來調(diào)用mas_updateConstraints,并不會(huì)觸發(fā)代理 heightForRowAtIndexPath,那怎么會(huì)更新高度呢。
既然是這樣,那我們就重新加載該列表吧。
[cell setHeightBlock:^(CGFloat imageHeight){
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
}];
我們更新完mas_updateConstraints后,這時(shí)候,直接刷新該列表,就可以解決問題了。
這時(shí)候我們重新運(yùn)行,效果還可以,但在來回滾動(dòng)的時(shí)候,發(fā)現(xiàn)有點(diǎn)卡。很明顯,我們滾動(dòng)的時(shí)候每次都要重新刷新cell。
如果我們有緩存了,那就知道了圖片的高度,那我們是不是就不需要reloadRowsAtIndexPaths。
所以我再次進(jìn)行優(yōu)化
// 是否有緩存
BOOL hasCache = [[SDImageCache sharedImageCache] diskImageDataExistsWithKey:model.urlStr];
[_ImageView sd_setImageWithURL:[NSURL URLWithString:model.urlStr] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
CGSize imageSize = image.size;
CGFloat maxWidth = kSCREEN_WIDTH - 32;
CGFloat height = imageSize.height * maxWidth / imageSize.width;
[self.imageView mas_updateConstraints:^(MASConstraintMaker *make) {
make.height.mas_equalTo(height);
}];
// 有緩存就不去reloadRowsAtIndexPaths
if (!hasCache && self.heightBlock) {
self.heightBlock(height);
}
}
}];
如果發(fā)現(xiàn)是有緩存圖片了,我們就不刷新列表了。sd_setImageWithURL這時(shí)候也是從緩存里面讀取圖片,就不是異步加載了,所以不用再次刷新了當(dāng)前cell了。
XHWebImageAutoSize
有的人說,這么寫好像挺麻煩的,有沒有封裝好的寫法,的確有的。
那就是第三方庫 XHWebImageAutoSize,它的寫法其實(shí)也是用了 SDWebImage 來進(jìn)行優(yōu)化操作的。
[_imageView sd_setImageWithURL:[NSURL URLWithString:model.urlStr] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
/** 緩存image size */
[XHWebImageAutoSize storeImageSize:image forURL:imageURL completed:^(BOOL result) {
/** reload */
if(result && self.heightBlock) {
self.heightBlock(0)
}
];
}
}];
緩存圖片后,一樣是去刷新cell。
[cell setHeightBlock:^(CGFloat imageHeight) {
[tableView xh_reloadDataForURL:[NSURL URLWithString:model.urlStr]];
}];
然后就是重新加載高度。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
ImageModel *model = _dataArray[indexPath.row];
return [XHWebImageAutoSize imageHeightForURL:[NSURL URLWithString:model.urlStr] layoutWidth:[UIScreen mainScreen].bounds.size.width-32 estimateHeight:200] + 50;
}
后面加的 50是其他的高度,例如cell里面還有title,就是圖片+其他高度。
這樣也能實(shí)現(xiàn)圖片自適應(yīng)高度。
僅加載當(dāng)前屏幕的內(nèi)容
圖片列表實(shí)在太多了,一直滑滑滑,圖片加載速度跟不上手速啊,感覺有點(diǎn)卡,我們可以僅加載當(dāng)前屏幕的內(nèi)容。滑動(dòng)的時(shí)候,我們不加載,等列表停后,我們?cè)俅渭虞d當(dāng)前屏幕的內(nèi)容。
這時(shí)候我們?cè)谀P?code>model里面,添加一個(gè)isLoad的參數(shù),如果是true,我們才加載。
先添加一個(gè)當(dāng)前屏幕加載cell的方法。
-(void)loadCurrentCells{
NSArray * array = [self.tableView indexPathsForVisibleRows];
for (NSIndexPath *indexPath in array) {
JJTableViewCell * cell = (JJTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
ImageModel *model = _dataArray[indexPath.row];
//設(shè)置為可以加載
model.isLoad = YES;
//配置cell
[cell configCellWithImageModel:model];
}
}
cell里面對(duì)model的isLoad進(jìn)行判斷。
- (void)configCellWithImageModel:(ImageModel *)model
{
if (model.isLoad) {
[_imageView sd_setImageWithURL:[NSURL URLWithString:model.urlStr]];
}else {
_imageView.image = [UIImage imageNamed:@"default_images_icon"];
}
}
如果暫不加載,我們可以先設(shè)置占用圖片。
這樣一來,我們只要監(jiān)聽停止滑動(dòng)的時(shí)候,我們就設(shè)置加載當(dāng)前頁面的內(nèi)容即可。
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self loadCurrentCells];
}
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self loadCurrentCells];
}
當(dāng)然一開始我們reloaData的時(shí)候,所有isload都為false,所以我們需要加載一次當(dāng)前cell內(nèi)容。
[self.tableView reloadData]; [self loadCurrentCells];
這樣,我們就可以做到一直滑動(dòng)的時(shí)候,不異步加載圖片,等滑動(dòng)停止再加載當(dāng)前屏幕的圖片。
當(dāng)然除了這種寫法,我們還可以通過RunLoop來實(shí)現(xiàn)。
預(yù)加載
所謂預(yù)加載,就是一直滑動(dòng),我們翻頁的時(shí)候,提前加載數(shù)據(jù)出來,讓用戶的感覺就是一直有數(shù)據(jù)。就沒有出現(xiàn)上拉加載更多這種情況。
總體思路是:當(dāng)滑動(dòng)距離占比到了總滑動(dòng)距離的時(shí)候的%90(不固定),就觸發(fā)預(yù)加載。
這里我就不寫了,直接把大佬的鏈接搞過來:iOS開發(fā) TableView 網(wǎng)絡(luò)請(qǐng)求/展示預(yù)加載
以上就是ios開發(fā)UITableViewCell圖片加載優(yōu)化詳解的詳細(xì)內(nèi)容,更多關(guān)于ios UITableViewCell圖片加載的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- iOS開發(fā)TableView網(wǎng)絡(luò)請(qǐng)求及展示預(yù)加載實(shí)現(xiàn)示例
- iOS ScrollView嵌套tableView聯(lián)動(dòng)滾動(dòng)的思路與最佳實(shí)踐
- iOS優(yōu)化UITableViewCell高度計(jì)算的一些事兒
- iOS自定義UITableView實(shí)現(xiàn)不同系統(tǒng)下的左滑刪除功能詳解
- iOS11解決UITableView側(cè)滑刪除無限拉伸的方法
- ios UITableView 自定義右滑刪除的實(shí)現(xiàn)代碼
- iOS開發(fā)學(xué)習(xí)TableView展現(xiàn)一個(gè)list實(shí)例
相關(guān)文章
IOS self和super詳解實(shí)現(xiàn)原理及區(qū)別
這篇文章主要介紹了iOS self和super詳解實(shí)現(xiàn)原理及區(qū)別的相關(guān)資料,這里不僅說明區(qū)別并介紹實(shí)現(xiàn)原理,具有參考價(jià)值,需要的朋友可以參考下2016-12-12
IOS開發(fā)之路--C語言基礎(chǔ)知識(shí)
當(dāng)前移動(dòng)開發(fā)的趨勢(shì)已經(jīng)勢(shì)不可擋,這個(gè)系列希望淺談一下個(gè)人對(duì)IOS開發(fā)的一些見解,今天我們從最基礎(chǔ)的C語言開始,C語言部分我將分成幾個(gè)章節(jié)去說,今天我們簡單看一下C的一些基礎(chǔ)知識(shí),更高級(jí)的內(nèi)容我將放到后面的文章中。2014-08-08
開發(fā)繪圖、手勢(shì)綜合App注意點(diǎn)
本篇文章主要給大家詳細(xì)講述了在IOS開發(fā)繪圖、手勢(shì)綜合App容易遇到的坑以及注意事項(xiàng)等內(nèi)容,有興趣的朋友參考下吧。2018-02-02
iOS UIWebView 通過 cookie 完成自動(dòng)登錄實(shí)例
本篇文章主要介紹了iOS UIWebView 通過 cookie 完成自動(dòng)登錄實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-04-04
Apple?Watch?App?Lifecycle應(yīng)用開發(fā)
這篇文章主要為大家介紹了Apple?Watch?App?Lifecycle應(yīng)用開發(fā)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10

