關(guān)乎到用戶體驗,離線緩存在一個完善成熟的App架構(gòu)中,似乎成了不可或缺的部分,本地數(shù)據(jù)加載的零延遲,能給用戶帶來更好的使用體驗。
在使用離線緩存數(shù)據(jù)時,第一個需要考慮的是<code>數(shù)據(jù)的實時性</code>,
數(shù)據(jù)的實時性對于不同的App或者不同的信息類型,都會有不一樣的要求,數(shù)據(jù)的實時性可以用來劃分不同的場景或者使用離線緩存的策略:
1、<code>數(shù)據(jù)實時性要求高:</code>這類信息數(shù)據(jù)變化頻繁,需要客戶端與服務(wù)器的數(shù)據(jù)保持高度統(tǒng)一,這種情況下總是優(yōu)先去請求網(wǎng)絡(luò)數(shù)據(jù)。
注意:
因為這類數(shù)據(jù)通常<code>“過期”</code>會帶來比較大的危險,所有如果顯示了本地數(shù)據(jù),應(yīng)禁用對應(yīng)的數(shù)據(jù)操作功能,并提示警告信息。

2、<code>數(shù)據(jù)實時性要求不高:</code>數(shù)據(jù)在服務(wù)器的變化不會很頻繁,客戶端可以優(yōu)先使用本地緩存數(shù)據(jù),讓用戶去選擇是否加載新的數(shù)據(jù)。通常這類數(shù)據(jù)在本地存在的時間越長,離線緩存的優(yōu)勢就越明顯。

3、<code>權(quán)衡利弊:</code>在一開始定好規(guī)則,在適當(dāng)?shù)臅r機或條件下,智能的去決定優(yōu)先使用哪方面的數(shù)據(jù)。

思考:
關(guān)于這一塊,不同的業(yè)務(wù)場景,業(yè)務(wù)需求,數(shù)據(jù)顯示邏輯,面對的可能都不一樣,所有還是需要在實際的開發(fā)中去拿捏分寸,巧妙的將數(shù)據(jù)存在本地,而又避免“過期數(shù)據(jù)”帶來的危險。
扯了這么多,如何使用coredata來做到這些事情呢?(這特么才是重點好么~)
前面已經(jīng)寫了兩篇關(guān)于coredata的簡單使用和coredata數(shù)據(jù)遷移的文章,現(xiàn)在就來談?wù)勅绾芜M階使用吧。
1、封裝:
數(shù)據(jù)操作無非增刪改查,這些方法必須進行封裝,那么封裝在哪呢?我們需要一個所有實體的基類:
<pre>
<code class='objc hljs'>
/**
- 實體基類
*/
@interface BaseEtt : NSManagedObject
//獲取類名
+(NSString*)className;
//創(chuàng)建一個新的實體
+(BaseEtt*) createEntity;
//根據(jù)where條件查詢實體
+(NSArray) selectEntityWithWhere:(NSString) where;
/**
- 根據(jù)條件升序查詢
- @param where 條件
- @param key 排序字段
- @return
/
+(NSArray) selectEntityWithWhere:(NSString) where byAsc:(NSString )key;
/ - 根據(jù)條件降序查詢
- @param where 條件
- @param key 排序字段
- @return
/
+(NSArray) selectEntityWithWhere:(NSString*) where byDesc:(NSString *)key;
/**
- 根據(jù)條件分頁查詢
- @param page 頁碼
- @param where 條件
- @return
/
+(NSArray) getListByPage:(PageInfo)page where:(NSString)where;
/**
- 保存實體
/
+(void) saveEntity;
/*
- 刪除實體
- @param entity
/
+(void) removeEntity:(BaseEtt) entity;
/** - 刪除所有實體
/
+(void) removeAll;
/* - 按條件刪除實體
- @param where
/
+(void) removeWithWhere:(NSString) where;
/** - 按條件刪除實體保存
- @param where
- @param save
/
+(void) removeWithWhere:(NSString) where SaveContext:(BOOL) save;
/**
- 判斷兩個實體是否相等
- @param entity 對比實體
- @return 是否相等
/
-(BOOL) isEqualToEntity:(BaseEtt) entity;
@end
</code></pre>
這里包含了常用的增刪該查的方法,一般在手機端所需要的數(shù)據(jù)查詢并不會怎么復(fù)雜,這些基本都能夠滿足日常使用,新建的實體繼承這個基類,這樣就可以很方便的使用這些方法了。
<code>isEqualToEntity</code>這個方法是用來比較服務(wù)器獲取數(shù)據(jù)轉(zhuǎn)化為實體后是否與本地的實體對象是否相等,所以需要在所有繼承它的子類進行重寫,至于條件的話,可以根據(jù)實際情況進行擴展,一般都是使用xxID之類的字段。
<code>PageInfo</code>是一個分頁對象,里面就兩個屬性,一個<code>PageIndex</code>,一個<code>PageSize</code>
2、判斷
這些數(shù)據(jù)大致會在三個地方:
1、<code>dataArray</code>(當(dāng)前頁面顯示數(shù)據(jù)存放的數(shù)組)
2、<code>tempArray</code>(從服務(wù)器獲取數(shù)據(jù)的臨時存放數(shù)組)
3、<code>localDB</code>(本地數(shù)據(jù)庫)
注:
這里不得不提的一點是,<code>coredata</code>是一個對象關(guān)系映射的數(shù)據(jù)持久化框架,它的實體對象是互相影響的,也可以說其實就是一個,所以<code>dataArray</code>的數(shù)據(jù)和<code>localDB</code>中的數(shù)據(jù)可以看成是一樣的,<code>dataArray</code>只是拿了<code>localDB</code>一部分而已.
我模擬了以下幾個常用的場景:
1、進入頁面請求服務(wù)器數(shù)據(jù),成功后的與本地數(shù)據(jù)的對比判斷:

2、上拉加載更多數(shù)據(jù)(分頁)

其它的判斷場景大致都差不多,只需要注意:
1、不要添加重復(fù)數(shù)據(jù)到本地,這將可能會導(dǎo)致數(shù)據(jù)錯亂
2、如果業(yè)務(wù)需要,一定要存儲多條相同的數(shù)據(jù)在本地,那么要記得用不同的標(biāo)記來區(qū)分,并且<code> isEqualToEntity </code>的重寫應(yīng)該要把這個標(biāo)記的判斷加進去。
3、一定要理解對象關(guān)系映射(ORM)的數(shù)據(jù)狀態(tài),注意實體對象的引用(例如:上級頁面用到這某個對象,在下級頁面將這個對象進行了remove,即使在你看來這是兩個不同的對象了,也是會導(dǎo)致上個頁面報空指針的異常)。
3、說點其它的:
其實標(biāo)題中的優(yōu)雅二字在我寫完后發(fā)現(xiàn)并不合適,在寫博客的過程中,有些之前沒想到的東西突然也變得豁然開朗,不過還是不得不說一句,coredata的水比較深,慎入?。。。ㄩ_玩笑)
附上github地址:<i class="am-icon-github"></i>coreDataTools