
問題一:App重啟后,NSCache中的東西還存在嗎?
一聽到緩存數(shù)據(jù),我們腦海里立馬浮現(xiàn)了《印象筆記》這樣“理所當(dāng)然”的功能:在WIFI環(huán)境中保存過的網(wǎng)絡(luò)文章,在沒有網(wǎng)絡(luò)時(比如出門在外,關(guān)閉4G),看過的文章可以繼續(xù)閱讀,并不受網(wǎng)絡(luò)關(guān)閉的影響。
NSCache可以幫助我們實現(xiàn)這樣的功能嗎?
并不能?。?!
NSCache中的數(shù)據(jù)在APP重啟(或重新init)后,都消失了,并不會保存下來。
也就是說,NSCache的正確名字應(yīng)該叫做NSMemoryCache,只是將數(shù)據(jù)保存在內(nèi)存中。
問題二:可以統(tǒng)計出NSCache中已經(jīng)緩存的數(shù)據(jù)大小嗎?
答案依然是否
我們可以使用 countLimit 指定緩存中保存的對象數(shù)量,
或用 totalCostLimit屬性 +
- (void)setObject:(id)obj forKey:(id)key cost:(NSUInteger)num方法,勉強實現(xiàn)占用內(nèi)存的控制。
注意:cost并沒有說明必須等于對象占用的字節(jié)數(shù)。
這意味NSCache到底占用了多少內(nèi)存,是使用者(就是苦逼的我們)自己計算的!
NSCache奇葩之處三:釋放內(nèi)存時,并不確定釋放的對象的順序。
這是什么意思呢?假設(shè)我們基于NSCache實現(xiàn)一個無限上拉的列表,當(dāng)上拉到某一頁,我們存入了當(dāng)前頁的數(shù)據(jù)對象,結(jié)果觸發(fā)了內(nèi)存警告,NSCache會自動釋放,結(jié)果可能是剛存入的數(shù)據(jù)對象被清理了,而不是我們希望的“先進先出”順序。
相信讀到這里,有些童鞋已經(jīng)出離憤怒了:這個奇葩緩存有什么用?
NSCache 是線程安全的
很多童鞋第一次實現(xiàn)TableView時,都會使用NSMutableArray當(dāng)數(shù)據(jù)源,當(dāng)實現(xiàn)下拉刷新時,何時清理這個數(shù)組就很重要了,如果TableView正在刷新,而數(shù)組又被清掉時,就會導(dǎo)致數(shù)組越界訪問而崩潰,而使用NSCache就不會有此問題。
結(jié)合NSDiscardableContent協(xié)議使用
實現(xiàn)了這個協(xié)議的類需要在被引用之前,必須調(diào)用beginContentAccess來標(biāo)記為可使用的,如果在使用之前沒有調(diào)用beiginContentAccess,那么就會拋出異常。在使用結(jié)束之后,調(diào)用endContentAccess,來標(biāo)記它為可以被釋放的。如果實現(xiàn)了NSDiscardableContent協(xié)議的對象放入了NSCache中,那么,在清除它的時候,會調(diào)用discardContentIfPossible方法來判斷引用狀況,沒有引用,則銷毀。
這樣,我們就可以很“精確”地控制對象的釋放,配合NSCache的內(nèi)存自動釋放,達(dá)到既釋放過期數(shù)據(jù)的目的,又不用擔(dān)心對象過早被釋放,如果另外實現(xiàn)這樣的效果,需要做數(shù)據(jù)有效性判斷,當(dāng)然是費時費力。
另外,NSCache的KEY是不需要遵循NSCopying協(xié)議的,也就是說,作為KEY的對象并不會被拷貝,利用這點,可以做出一些NSDictionary無法實現(xiàn)的效果,請關(guān)注溪石iOS,了解更多開發(fā)技巧。