Core Data基礎
Core Data是一個API集合,被設計用來簡化數據對象的持久存儲。
在此先不普及概念,先通過一個簡單的案例使用來感受一下Core Data的精妙之處。
在創建工程的時候勾選Use Core Data.

創建好項目,我們可以看到在左側任務欄多了一個CoreDataDemo.xcdatamodeld。暫且先不管這個文件。

此時如果我們打開AppDelegate.h和AppDelegate.m文件,會發現比平時多了很多的內容。
下面是生成的聲明文件和實現文件。

1 #import <UIKit/UIKit.h> 2 #import <CoreData/CoreData.h> 3 4 @interface AppDelegate : UIResponder <UIapplicationDelegate> 5 6 @PRoperty (strong, nonatomic) UIWindow *window; 7 8 @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 9 @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;10 @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;11 12 - (void)saveContext;13 - (NSURL *)applicationDocumentsDirectory;14 @end

1 #import "AppDelegate.h" 2 3 @interface AppDelegate () 4 5 @end 6 7 @implementation AppDelegate 8 9 10 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 11 // Override point for customization after application launch. 12 return YES; 13 } 14 15 - (void)applicationWillResignActive:(UIApplication *)application { 16 // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 17 // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 18 } 19 20 - (void)applicationDidEnterBackground:(UIApplication *)application { 21 // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 22 // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 23 } 24 25 - (void)applicationWillEnterForeground:(UIApplication *)application { 26 // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 27 } 28 29 - (void)applicationDidBecomeActive:(UIApplication *)application { 30 // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 31 } 32 33 - (void)applicationWillTerminate:(UIApplication *)application { 34 // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 35 // Saves changes in the application's managed object context before the application terminates. 36 [self saveContext]; 37 } 38 39 #pragma mark - Core Data stack 40 41 @synthesize managedObjectContext = _managedObjectContext; 42 @synthesize managedObjectModel = _managedObjectModel; 43 @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 44 45 - (NSURL *)applicationDocumentsDirectory { 46 // The directory the application uses to store the Core Data store file. This code uses a directory named "com.wyg.CoreDataDemo" in the application's documents directory. 47 return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 48 } 49 50 - (NSManagedObjectModel *)managedObjectModel { 51 // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 52 if (_managedObjectModel != nil) { 53 return _managedObjectModel; 54 } 55 NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataDemo" withExtension:@"momd"]; 56 _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 57 return _managedObjectModel; 58 } 59 60 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 61 // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 62 if (_persistentStoreCoordinator != nil) { 63 return _persistentStoreCoordinator; 64 } 65 66 // Create the coordinator and store 67 68 _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 69 NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataDemo.sqlite"]; 70 NSError *error = nil; 71 NSString *failureReason = @"There was an error creating or loading the application's saved data."; 72 if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 73 // Report any error we got. 74 NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 75 dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 76 dict[NSLocalizedFailureReasonErrorKey] = failureReason; 77 dict[NSUnderlyingErrorKey] = error; 78 error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 79 // Replace this with code to handle the error appropriately. 80 // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 81 NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 82 abort(); 83 } 84 85 return _persistentStoreCoordinator; 86 } 87 88 89 - (NSManagedObjectContext *)managedObjectContext { 90 // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 91 if (_managedObjectContext != nil) { 92 return _managedObjectContext; 93 } 94 95 NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 96 if (!coordinator) { 97 return nil; 98 } 99 _managedObjectContext = [[NSManagedObjectContext alloc] init];100 [_managedObjectContext setPersistentStoreCoordinator:coordinator];101 return _managedObjectContext;102 }103 104 #pragma mark - Core Data Saving support105 106 - (void)saveContext {107 NSManagedObjectContext *managedObjectContext = self.managedObjectContext;108 if (managedObjectContext != nil) {109 NSError *error = nil;110 if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {111 // Replace this implementation with code to handle the error appropriately.112 // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.113 NSLog(@"Unresolved error %@, %@", error, [error userInfo]);114 abort();115 }116 }117 }118 119 @end
可能初次接觸感覺密密麻麻的,那我們暫且也不用管它,既然系統為我們自動生成,我們直接使用就行了。
現在我們點擊進去CoreDataDemo.xcdatamodeld這個文件,我們可以看到下面的界面。

Add Entity(添加實體) Add Attribute(添加屬性) Editor Style(編輯風格)
現在我們添加一個Entity,命名為People,添加屬性name,age
現在我們再添加一個Entity,命名位Book,添加屬性name,author

現在我們可以添加People和Book的關系。
在上圖中我們可以看到Relationships這個詞(顯示的是People,Book這一同理)。
我們想要在People中添加一個Book,表名Book是People的一個屬性,可以簡單理解為人有書
在Book中添加一個People,表名People是Book的一個屬性,可以簡單理解為書有主人

此時選擇Editor Style,我們可以看到下圖:

我們使用界面圖形工具創建了一個People,一個Book,我們如何讓他們生成實際的類呢?
選擇菜單欄中的 Editor->create NSManagedObject subclass(也可以在command+n->Core Data->NSManagedObject subclass)


執行完上述步驟系統會為我們生成People,Book類。

下面是Book和People類文件,其中People類中我們發現NSManagedObject修飾book,我們將其修改位Book就行,并寫上@class Book;有時會出現這個小問題。

1 #import <Foundation/Foundation.h> 2 #import <CoreData/CoreData.h> 3 4 @class People; 5 6 @interface Book : NSManagedObject 7 8 @property (nonatomic, retain) NSNumber * name; 9 @property (nonatomic, retain) NSString * author;10 @property (nonatomic, retain) People *people;11 12 @end

1 #import "Book.h" 2 #import "People.h" 3 4 5 @implementation Book 6 7 @dynamic name; 8 @dynamic author; 9 @dynamic people;10 11 @end

1 #import <Foundation/Foundation.h> 2 #import <CoreData/CoreData.h> 3 4 5 @interface People : NSManagedObject 6 7 @property (nonatomic, retain) NSString * name; 8 @property (nonatomic, retain) NSNumber * age; 9 @property (nonatomic, retain) NSManagedObject *book;10 11 @end

1 #import "People.h" 2 3 4 @implementation People 5 6 @dynamic name; 7 @dynamic age; 8 @dynamic book; 9 10 @end
到現在為止,萬事俱備,只欠代碼了。
我們對Core Data的操作,無外乎增刪改查,直接上代碼
在AppDelegate啟動函數中,添加以下代碼是往Core Data中添加一條記錄:

1 //托管對象上下文,有點類似于數據庫 2 NSManagedObjectContext *context = self.managedObjectContext; 3 //實例,有點類似于表,插入一條數據,并給對象屬性賦值 4 People *people = [NSEntityDescription insertNewObjectForEntityForName:@"People" inManagedObjectContext:context]; 5 people.name = @"wyg"; 6 7 Book *book =[NSEntityDescription insertNewObjectForEntityForName:@"Book" inManagedObjectContext:context]; 8 book.name = @"三國演義"; 9 10 people.book = book;11 12 [self saveContext];

1 NSManagedObjectContext *context = self.managedObjectContext; 2 NSEntityDescription *entity = [NSEntityDescription entityForName:@"People" inManagedObjectContext:context]; 3 NSFetchRequest *request = [NSFetchRequest new]; 4 request.entity = entity; 5 NSArray *arr = [context executeFetchRequest:request error:nil]; 6 7 for (People *object in arr) 8 { 9 NSLog(@"%@,%@",object.name,object.book.name);10 }
查得結果:

關于修改和刪除,跟上面原理差不多,首先是查找結果集,假設要刪除某條數據,可以使用:[context deleteObject:object];
對某條數據修改,可以直接使用:[object setValue:@"小明" forKey:@"name"];//將姓名修改為小明。
1.Key 0x889f2f0(:Key:0x889e400<-://981A476D-55AC-4CB4-BBD8-E0285E522412/Key/p1489> ; data: <fault>)
出現的可能原因:當時我創建的時候,勾選了core data,它會在delegate.m文件中生成一些操作,但是如果你在其它控制器中想要操作的話,就要獲取core data的相關對象,我的當時的做法是:

1 app = [AppDelegate new];2 NSManagedObjectContext *context = app.managedObjectContext;3 NSEntityDescription *entity = [NSEntityDescription entityForName:@"NoteModel" inManagedObjectContext:context];4 NSFetchRequest *request = [NSFetchRequest new];5 request.entity = entity;6 [request setReturnsObjectsAsFaults:NO];7 notes = [context executeFetchRequest:request error:nil];8 [collection reloadData];
如果我將app設置位局部變量,就會出現上述錯誤,我的解決辦法是將其設置為全局變量。具體原因可以參考:http://imtx.me/archives/1888.html
新聞熱點
疑難解答