亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

UITableView中大圖片加載時卡頓問題

UITableView中大圖片加載時卡頓問題

SMILET 2019-03-29 11:00:18
我的UITableView中有若干UIButton,圖片存放于本地硬盤,讀取到內存后放進UIButton展示。子線程負責從文件讀入圖片到內存,主線程用setImage:forState:展示。由于setImage:forState:耗時較長且在主線程,導致Table拖動起來較卡。代碼如下(UIButton上的擴展):-(void)asyncLoadImageAtPath:(NSString*)fullPathforState:(UIControlState)state{dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{UIImage*image=[[UIImagealloc]initWithContentsOfFile:fullPath];dispatch_async(dispatch_get_main_queue(),^{[selfsetImage:imageforState:state];});});}后將setImage:forState:移入子線程,卡是不卡了,但是setImage:forState線程不安全,setImage:forState調用兩秒后才會被顯示。代碼改為:-(void)asyncLoadImageAtPath:(NSString*)fullPathforState:(UIControlState)state{dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{UIImage*image=[[UIImagealloc]initWithContentsOfFile:fullPath];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0),^{[selfsetImage:imageforState:state];});});}QQ電影票中存于本地的大圖拖起來不卡,且看起來是線程安全的。不知是怎么做的?解決:最后讀圖重畫成小尺寸一個線程,渲染一個線程,性能和自帶的Photos差不多
查看完整描述

2 回答

?
絕地無雙

TA貢獻1946條經驗 獲得超4個贊

最近從4s換回3GS,測試TavleView插圖非??ǎ谑菧y試了一下,發現initWithContentsOfFile并不是造成卡頓的主兇。因為這個動作本來就不在mainqueue里邊的。而setImage必須是在mainqueue。于是寫代碼在本地生成一些更小的縮略圖例如原本240px的直接縮放成80px,發現會快得多。我的解決方法是:
1、寫代碼在http下載圖片的completeblock里面順便把圖片縮放成另外一個大小,另存一份。
2、cellforrow代碼://先把id記錄下來,這是在cell里面加的property
cell.objectIdforThisCell=**這個cell所代表的對象的id**;
//在這個block里面的id,到這一步是設置為cell.objectIdforThisCell一樣的
NSString*blockObjectid=cell.objectIdforThisCell;
dispatch_async(imagequeue,^{
UIImage*image=[[UIImagealloc]initWithContentsOfFile:小圖文件path];
dispatch_async(dispatch_get_main_queue(),
^{
[selfsetImage:imageforState:state];
});
image=[[UIImagealloc]initWithContentsOfFile:大圖文件path];
dispatch_async(dispatch_get_main_queue(),
^{
if([cell.objectIdforThisCellisEqualToString:blockObjectid]){
//關鍵在這里,當列表拖動速度很快的時候,cell的property已經被修改(因為reuse了),但是blockObjectid在這個線程里面還是舊的。
//當它們****不相等****,這個cell就是刷太快而被另外一個線程用上了,也就是說,這張大圖已經不再需要輸出到cell里面了(被另外一個線程的另外一張圖沖掉了)
//這樣一來,在列表快速拖動的時候,瞬間把低清晰的圖像給貼上去,等拖動速度慢下來之后,再貼高清晰的圖,用戶也感覺不出來,也不卡了。
[selfsetImage:imageforState:state];
}
});
});
dispatch_release(imagequeue);把圖片變小:CGSizenewSize=CGSizeMake(80,80);
UIGraphicsBeginImageContextWithOptions(newSize,NO,0.0);
[imgdrawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
newImage=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
                            
查看完整回答
反對 回復 2019-03-29
?
侃侃無極

TA貢獻2051條經驗 獲得超10個贊

先在其他線程做asyncloading,就是其中的initWithContentsOfFile,然后當imageloading完了再調用主線程updateUI.dispatch_queue_timagequeue=dispatch_queue_create("com.company.imageLoadingQueue",NULL);
//Startthebackgroundqueue
dispatch_async(imagequeue,^{
UIImage*image=[[UIImagealloc]initWithContentsOfFile:fullPath];
dispatch_async(dispatch_get_main_queue(),
^{
[selfsetImage:imageforState:state];
});//endofmainthreadqueue
});//endofimagequeue
dispatch_release(imagequeue);
                            
查看完整回答
反對 回復 2019-03-29
  • 2 回答
  • 0 關注
  • 405 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號