iOS中 常用的資料持久化方法
對啊 就這麼簡單。
iOS中的資料持久化方式,基本上有以下四種:屬性列表、物件歸檔、SQLite3和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.SQLite3 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];