在程式開發中,數據層永遠是程式的核心結構之一。我們將現實事物進行抽象,使之變成一個個數據。對這些數據的加工處理是代碼中能體現技術水平的一大模塊,比如數據的請求、解析、緩存、持久化等等。適當的對數據進行持久化存儲可以實現應用的離線功能,以此提高用戶體驗。在iOS開發中,蘋果提供了四種持久化方案供我們選 ...
在程式開發中,數據層永遠是程式的核心結構之一。我們將現實事物進行抽象,使之變成一個個數據。對這些數據的加工處理是代碼中能體現技術水平的一大模塊,比如數據的請求、解析、緩存、持久化等等。適當的對數據進行持久化存儲可以實現應用的離線功能,以此提高用戶體驗。在iOS開發中,蘋果提供了四種持久化方案供我們選擇。這些方案分別包括屬性列表(plist)、數據歸檔(NSKeyedValueArchiver/NSUserDefaults)、資料庫(sqlite)和coreData等
1.屬性列表
屬性列表是一種明文的輕量級存儲方式,其存儲格式有多種,最常規格式為XML格式。在我們創建一個新的項目的時候,Xcode會自動生成一個info.plist文件用來存儲項目的部分系統設置。plist只能用數組(NSArray)或者字典(NSDictionary)進行讀取,由於屬性列表本身不加密,所以安全性幾乎可以說為零。因為,屬性列表正常用於存儲少量的並且不重要的數據。
在程式啟動後,系統會自動創建一個NSUserDefaults的單例對象,我們可以獲取這個單例來存儲少量的數據,它會將輸出存儲在.plist格式的文件中。其優點是像字典一樣的賦值方式方便簡單,但缺點是無法存儲自定義的數據。
涉及到的主要類:NSUserDefaults,一般 [NSUserDefaults standardUserDefaults]就夠用了
@interface User : NSObject <NSCoding>
@property (nonatomic, assign) NSInteger userID;
@property (nonatomic, copy) NSString *name;
@end
使用方法
1).分開存取
// 存
[[NSUserDefaults standardUserDefaults] setInteger:userID forKey:@”userID”];
[[NSUserDefaults standardUserDefaults] setObject:name forKey:@”name”];
// 取
NSInteger uId = [[[NSUserDefaults standardUserDefaults] integerValueForKey:@”userID”];
NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:@”name”];
2).按對象存取
// 存
[[NSUserDefaults standardUserDefaults] setObject:self forKey:@”user”];
// 取
User *u = [[NSUserDefaults standardUserDefaults] objectForKey”@”user”];
2.對象歸檔
與屬性列表相反,同樣作為輕量級存儲的持久化方案,數據歸檔是進行加密處理的,數據在經過歸檔處理會轉換成二進位數據,所以安全性要遠遠高於屬性列表。另外使用歸檔方式,我們可以將複雜的對象寫入文件中,並且不管添加多少對象,將對象寫入磁碟的方式都是一樣的。
使用NSKeyedArchiver對自定義的數據進行序列化,並且保存在沙盒目錄下。使用這種歸檔的前提是讓存儲的數據模型遵守NSCoding協議並且實現其兩個協議方法。
大部分Object C對象都符合NSCoding協議,也可以在自定義對象中實現NSCoding協議,要實現NSCoding協議,實現兩個方法:
- (void) encodeWithCoder:(NSCoder *)encoder 與 -(void)initWithCoder:(NSCoder *)encoder
同時,建議對象也同時實現NSCopying協議,該協議允許複製對象,要實現NSCopying協議須實現 -(id)copyWithZone:(NSZone *)zone 方法 。
@interface User : NSObject <NSCoding>
@property (nonatomic, assign) NSInteger userID;
@property (nonatomic, copy) NSString *name;
@end
@implementation User
// 以下兩個方法一定要實現,不然在調用的時候會crash
- (void)encodeWithCoder:(NSCoder *)aCoder;
{
// 這裡放置需要持久化的屬性
[aCoder encodeObject:[NSNumber numberWithInteger:self.userID] forKey:@”userID”];
[aCoder encodeObject:self.name forKey:@"name"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [self init])
{
// 這裡務必和encodeWithCoder方法裡面的內容一致,不然會讀不到數據
self.userID = [[aDecoder decodeObjectForKey:@"userID"] integerValue];
self.name = [aDecoder decodeObjectForKey:@"name"];
}
return self;
}
// 使用方法
+ (BOOL)save {
NSError *error = nil;
// 確定存儲路徑,一般是Document目錄下的文件
NSString* fileName = [self getFileName];
NSString* filePath = [self getFilePath];
if (![[NSFileManager defaultManager] createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:&error]) {
NSLog(@”創建用戶文件目錄失敗”);
return NO;
}
return [NSKeyedArchiver archiveRootObject:self toFile:[fileName:userId]];
}
@end
3.資料庫
sqlite是一個輕量級、跨平臺的小型資料庫,其擁有可移植性高、有著和MySql幾乎相同的資料庫語句以及無需伺服器即可使用的優點:
一、可以存儲大量的數據,存儲和檢索的速度非常快;二、能對數據進行大量的聚合,這樣比起使用對象來進行這些操作要快。
當然,它也具有明顯的缺點:
一、它沒有提供資料庫的創建方式;
二、它基於C語言框架設計,沒有面向對象的API,所以使用起來比較麻煩;
三、複雜的數據模型的數據建表相對而言比較麻煩。
4.coreData
coreData是蘋果官方iOS5之後推出的綜合型資料庫,其使用了ORM(Object Relational Mapping)對象關係映射技術,將對象轉換成數據,存儲在本地資料庫中。coreData為了提高效率,甚至將數據存儲在不同的資料庫中,且在使用的時候將本地數據放到記憶體中使得訪問速度更快。我們可以選擇coreData的數據存儲方式,包括sqlite、xml等格式。但也正是coreData 是完全面向對象的,其在執行效率上比不上原生的資料庫。除此之外,coreData擁有數據驗證、undo等其他功能,在功能上是四種持久化方案最多的。