2012-07-16 52 views
11

我剛剛在NSURLCache上花了太多時間尖叫我的頭,所以我提供了一些建議,希望其他人可以避免我的不幸。NSURLCache在iOS5上提供不一致的結果,看似隨機

這一切都開始合理。我的新應用項目只針對iOS 5及以上版本,所以我想我可以利用新的NSURLCache實現來滿足我所有的Web緩存需求。我需要一個NSURLCache的自定義子類來處理一些特殊的任務,但這一切似乎都得到了API的有力支持。文檔的快速閱讀,我去比賽:

[NSURLCache setSharedURLCache:[[MyCustomCache alloc] initWithMemoryCapacity:8 * 1024 * 1024 //8mb 
                    diskCapacity:32 * 1024 * 1024 // 32mb 
                     diskPath:@"webcache.db"]]; 

我想,一個8MB緩存是好的開始,我會用較大的磁盤高速緩存支持它,所以我們可以爲更多的我們在本地放大圖片。我將其餘的網絡代碼連接到NSURLConnection(實際上,我使用了MKNetworkKit,但事實證明這是無關緊要的),並期望從我的緩存中得到很大的幫助。當然,所有應該被緩存的請求都會盡快地保存到緩存中,並且當響應從緩存中提供時,它們會盡快飛回。這是彭贊斯海盜的常規制作,在我的網絡堆棧中有很多職責。

除了東西沒有加起來。可以從緩存提供的請求仍然通過網絡傳出。除非他們不是。 它看起來完全是隨機的並且是間歇性的,緩存是否實際用於提供請求。我沮喪地扯掉了我的頭髮,並且逐字地挖掘了試圖弄清楚發生了什麼的一切。我構建測試應用程序,在各處設置斷點,查看包裹蹤跡,讀取互聯網上提到NSURLCache的每一個單詞,試驗緩存控制標題,註釋掉代碼,繞過我的子類,甚至通過艱苦地追蹤組裝NSURLCache及其CFNetworking朋友,試圖瞭解底下有什麼神祕的邏輯。我極大地提高了我對ARM和Objective-C調用約定的認識,並且瞭解了一些關於低級別調試的知識,但在實際中弄清楚發生了什麼並沒有什麼意義。整個事情比海盜王的良性專政感覺更像Iolanthe的Nightmare Song,我幾乎要把它扔掉。

TL/DR版本:NSURLCache似乎可以正常工作,但即使它有可用的結果,它也不會返回緩存的結果。

+0

你是否試圖對NSURLConnection,UIWebView或兩者使用緩存?幾個月前,我在WWDC上與Safari開發人員討論了UIWebView緩存。他說有一種雙層緩存。從我自己的調試測試中,我發現在檢查OS級Safari緩存之前檢查了「+ [NSURLCache sharedURLCache]」。但是,響應不會緩存在應用程序的共享緩存中,並且誰知道操作系統級緩存的行爲如何。 – goldierox 2012-08-14 20:10:22

+0

有趣。我只專注於NSURLConnection方面,因爲我們的應用程序沒有太多使用UIWebView。我記得讀過應用程序未使用OS級Safari緩存,但我相信情況並非如此,特別是對於UIWebView。 – 2012-10-15 18:35:44

回答

9

最後,我嘗試了所有我一直在擺弄的位的不同排列。我將內存和磁盤緩存大小都設置爲8mb。

你看,所有的怪異消失!應該緩存的所有內容都將被保存。並且所有應該來自緩存的內容都會在沒有網絡請求的情況下得到處理。

看來,iOS5中的NSURLCache實現仍然不完整。它確實使用了磁盤和內存緩存(與iOS4和更早版本不同,它只實現了內存中緩存),但實際上並沒有在請求丟失時通過內存緩存傳遞到磁盤緩存。因此,它基本上是盲目的運氣(好,盲目運氣受所有其他網絡和緩存使用的影響)是否給定的響應恰好在內存中,或者不在正確的瞬間。這對於減少設備上的閃存文件IO可能是有用的,但如果您期望該類的理性行爲,則會非常令人討厭。

對於笑聲和歡快的舞蹈,我檢查了我的兩行修正並加速了對吧,最終與SO(和一個Apple bug報告)分享這個知識,希望沒有其他人擁有再次經歷這種痛苦。

這個故事的寓意:如果你嘗試在iOS5上使用NSURLCache並且磁盤容量大於內存容量,就會發生奇怪和邪惡的事情。不要這樣做。並避免製造魔法仙女的敵人。這裏

+0

我很遺憾地說這不適合我。 – bogardon 2012-07-26 13:24:49

+0

它爲我提供了很多好處,但之後我仍然有些不可思議。看起來NSURLCache存在一些嚴重的同步問題(?)。我已經提交了一個雷達,並在此期間,結束了我的所有圖像緩存到SDWebImage(https://github.com/rs/SDWebImage),至少表現確定性的一個漂亮的黑客。 – 2012-07-26 19:07:49

2

FWIW是我的最終解決方案:

https://gist.github.com/3245415

它需要使用FMDB,但效果都還不錯。

+0

不錯的做法。我想過嘗試這樣的事情,但當它明顯表現得如此難以預測時,我最終還是對自己的SQLite數據庫非常謹慎。我會擔心與您的修復同步問題,但也許這一切都在實踐中。正如我上面所說的,我一直在使用一個支持NSCache的SDWebImage分支(請參閱pull請求)來處理圖像緩存,並對結果非常滿意。 – 2012-08-07 20:12:49