iOS中的數據持久化方式

iOS中的數據持久化方式,基本上有以下四種:屬性列表(NSUserDefaults)、對象歸檔、SQLite和Core Data


1.屬性列表
涉及到的主要類: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.對象歸檔
要使用對象歸檔,對象必須實現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
SQLite是一個開源的嵌入式關係數據庫,它在2000年由D. Richard Hipp發佈,它的減少應用程序管理數據的開銷,SQLite可移植性好,很容易使用,很小,高效而且可靠。
SQLite嵌入到使用它的應用程序中,它們共用相同的進程空間,而不是單獨的一個進程。從外部看,它並不像一個RDBMS,但在進程內部,它卻是完整的,自包含的數據庫引擎。 嵌入式數據庫的一大好處就是在你的程序內部不需要網絡配置,也不需要管理。因爲客戶端和服務器在同一進程空間運行。SQLite 的數據庫權限只依賴於文件系統,沒有用戶帳戶的概念。SQLite 有數據庫級鎖定,沒有網絡服務器。它需要的內存,其它開銷很小,適合用於嵌入式設備。你需要做的僅僅是把它正確的編譯到你的程序。
關於SQLite的開發資料較多,這裏不再細說。只是建議不直接操作SQLite庫,而是採用一些開源的第三方庫來進行操作。比如:
FMDB:https://github.com/ccgus/fmdb.git
對SQLite都做了不錯的封裝。


4.Core Data
Core Data本質上是使用SQLite保存數據,但是它不需要編寫任何SQL語句。


要使用Core Data,需要在Xcode中的數據模型編輯器中設計好各個實體以及定義好他們的屬性和關係。之後,通過操作這些對象,結合Core Data完成數據的持久化:


NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSError *error;
NSString *fieldName = [NSString stringWithFormat:@"test%d", i];
UITextField *theField = [self valueForKey:fieldName];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//創 建描述語句,需求Line對象。類似於在數據庫中限定爲Line表。
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Line"  inManagedObjectContext:context];
[request setEntity:entityDescription];
//創建限制性語句,類似於SQL語句中的 where lineNum = i
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(lineNum = %d)", i];
[request setPredicate:pred];
NSManagedObject *theLine = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil){
NSLog(@”There was an error!”);
// Do whatever error handling is appropriate
}
if ([objects count] > 0){    //如果符合條件的object存在,則取出
theLine = [objects objectAtIndex:0];
}
else {  //如果不存在,則插入一個新的.
theLine = [NSEntityDescription insertNewObjectForEntityForName:@"Line"
inManagedObjectContext:context];
[theLine setValue:[NSNumber numberWithInt:i] forKey:@”lineNum”];  //設置這個object的屬性,coredata會自動將其寫入sqlite
[theLine setValue:theField.text forKey:@"lineText"];
[request release];

}


下面是其取數據的過程:


Core_Data_PersistenceAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Line"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil)
{
NSLog(@”There was an error!”);
// Do whatever error handling is appropriate
}
//每一個對象在CoreData中都表示爲一個NSManagedObject對象(類似於數據庫表中的每一行),他的屬性通過鍵/值 方式獲取
for (NSManagedObject *oneObject in objects)
{
NSNumber *lineNum = [oneObject valueForKey:@"lineNum"];
NSString *lineText = [oneObject valueForKey:@"lineText"];
}
[request release];

原帖地址:http://www.cocoachina.com/bbs/read.php?tid=137443

 

發佈了18 篇原創文章 · 獲贊 1 · 訪問量 9398
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章