最近研究了一下UITbleView中異步加載網(wǎng)絡(luò)圖片的問題吁津,iOS應(yīng)用經(jīng)常會看到這種界面煤墙。
一個tableView上顯示一些標(biāo)題痢甘、詳情等內(nèi)容距误,在加上一張圖片簸搞。
這里說一下這種思路。
為了防止圖片多次下載深寥,我們需要對圖片做緩存攘乒,緩存分為內(nèi)存緩存與沙盒緩存,我們當(dāng)然兩種都要實現(xiàn)惋鹅。
由于tableViewCell是有重用機(jī)制的则酝,也就是說,內(nèi)存中只有當(dāng)前可見的cell數(shù)目的實例闰集,滑動的時候沽讹,新顯示cell會重用被滑出的cell對象。這樣就存在一個問題:
一般情況下在我們會在cellForRow方法里面設(shè)置cell的圖片數(shù)據(jù)源武鲁,也就是說如果一個cell的imageview對象開啟了一個下載任務(wù)爽雄,這個時候該cell對象發(fā)生了重用,新的image數(shù)據(jù)源會開啟另外的一個下載任務(wù)沐鼠,由于他們關(guān)聯(lián)的imageview對象實際上是同一個cell實例的imageview對象挚瘟,就會發(fā)生2個下載任務(wù)回調(diào)給同一個imageview對象。這個時候就有必要做一些處理饲梭,避免回調(diào)發(fā)生時乘盖,錯誤的image數(shù)據(jù)源刷新了UI。
所以在我們向下滑動tableview的時候我們需要手動去取消掉下載操作憔涉,當(dāng)用戶停止滑動订框,再去執(zhí)行下載操作。SDWebImage采用的也是這種策略兜叨。
很簡單我們只需要監(jiān)聽ScrollView的代理方法(tableview繼承自Scrollview)穿扳。
而SDWebImage才用的就是這種方式,所以在運行SDWebImage的demo的時候衩侥,可以看到,如果快速滑下去矛物,然后又滑回來的話茫死,圖片是過了一會才顯示出來,這是因為快速滑動的時候泽谨,舊數(shù)據(jù)源的下載任務(wù)被取消掉了璧榄。
/—————————————————————------------------------
下面介紹一下具體的思路。
異步下載圖片我們用的是NSOperation吧雹,并且創(chuàng)建一個全局的queue來管理下載圖片的操作骨杂。
另外需要兩個字典operations、images
在把圖片顯示到Cell上之前
先判斷內(nèi)存中(images字典中)有沒有圖片雄卷,
如果有搓蚪,則取出url對應(yīng)的圖片來顯示,
如果沒有丁鹉,再去沙盒緩存中查看妒潭,當(dāng)然存到沙盒中都是NSData。
如果沙盒緩存中有揣钦,我們?nèi)〕鰧?yīng)的數(shù)據(jù)給Cell去顯示
如果沙盒中也沒有圖片雳灾,我們先顯示占位圖片。再創(chuàng)建operation去執(zhí)行下載操作了冯凹。
當(dāng)然在創(chuàng)建operation之前谎亩,我們要判斷這個operation操作是否存在
這個時候就用到我們operations這個字典了.
如果沒有下載操作,我們才需要真正的去創(chuàng)建operation執(zhí)行下載宇姚。
創(chuàng)建好下載操作之后應(yīng)該把該操作存放到全局隊列中去異步執(zhí)行匈庭,同時把操作放入operations字典中記錄下來。
下載完成之后:
把下載好的圖片放到內(nèi)存中浑劳、同時存到沙盒緩存中
下面存放到沙盒中的代碼可以定義成宏阱持,具體可以看后面的樣例:
執(zhí)行完上面的操作之后回到主線程刷新表格,
從operations字典中移除下載操作(防止operations越來越大魔熏,同時保證下載失敗后衷咽,能重新下載)
[圖片上傳中。蒜绽。兵罢。(7)]
這里我們不用[self.tableView reloadata],因為會刷新整個cell滓窍,浪費性能。
當(dāng)然如果你的下載操作里面需要做的事情很多的時候巩那,可以考慮自定義operation吏夯。 由于我這里只是簡單的下載小圖就沒有自定義operation了此蜈。注意要自己創(chuàng)建自動釋放池。
另外清理緩存的功能也沒有做
有興趣的朋友可以自己嘗試下.
至此基本實現(xiàn)思路已經(jīng)完成了噪生,這時候你會發(fā)現(xiàn)其實真正在項目中,以上代碼并沒有什么卵用。因為這個操作够吩,SDWebImgae已經(jīng)都封裝好砍聊,用一句代碼就搞定了,并且這句代碼代表的內(nèi)容比上面的操作更加完善桨嫁。??