經過上一篇iPhone開發之SQLite的學習,基本學會了 SQLite在iPhone中的使用,這時候我就在找有沒有SQLite的封裝類,這樣能夠避免本身重複地SQLite的封裝代碼,Google一下,找 到幾個objc-sqlite、FMDB等,還有一些其它不知名的封裝庫,官方也提供了CoreData框架來提供完整的對象持久化存儲方案,仍是有必要 要學習一下。sql
在CoreData有一些概念剛學習的時候不是很容易理解,仍是要單獨拿出來來梳理一下,這樣學後面的內容不會感受吃力。數據庫
從圖1中咱們能夠看到,在數據庫結構中的一些術語,在這裏會有對應,但不是所有。xcode
從圖2中咱們能夠看到一些數據庫操做方面的一些術語緩存
還有一些類NSManagedObjectModel、NSFetchRequest什麼的,具體項目就會有體會,下面來實戰一下。框架
新建一個項目,項目模板基於「Master-Detail Application」,點擊「Next」按鈕,項目命名爲「SimpleCoreData」,並勾選「Use Core Data」,點擊「Next」,選擇項目保存的目錄,點擊「Create」按鈕,項目建立完畢。函數
比之前建立的簡單項目多了很多代碼,還有xcdatamodeld文件,慢慢分析代碼,AppDelegate.h頭文件中,添加了三個property學習
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
再分析AppDelegate.m文件,有對應的三個方法來返回各自對應的對象fetch
#pragma mark - Core Data stack - (NSManagedObjectContext *)managedObjectContext{ ... return __managedObjectContext;} - (NSManagedObjectModel *)managedObjectModel{ ... return __managedObjectModel;} - (NSPersistentStoreCoordinator *)persistentStoreCoordinator{ ... return __persistentStoreCoordinator;}
這些對象在哪裏被調用的呢,打開MasterViewController.m,在初始化函數中,咱們看到經過獲取delegate,再經過 delegate調用方法managedObjectContext,這樣就獲得了這個NSManagedObjectContext對 象,NSManagedObjectContext對象它會跟NSPersistentStoreCoordinator對象打交 道,NSPersistentStoreCoordinator會去處理底層的存儲方式。atom
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{ self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); id delegate = [[UIApplication sharedApplication] delegate]; self.managedObjectContext = [delegate managedObjectContext]; } return self;}
分析MasterViewController.m的代碼發現如下函數的調用順序。spa
最後是從fetchedResultsController獲取到查詢結果,那就有必要來分析一下
- (NSFetchedResultsController *)fetchedResultsController{ // 若是查詢結果已經存在就直接返回__fetchedResultsController if (__fetchedResultsController != nil) { return __fetchedResultsController; } // 1.建立NSFetchRequest對象(至關於SQL語句) NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // 2.建立查詢實體(至關於設置查詢哪一個表) NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; [fetchRequest setEntity:entity]; // 設置獲取數據的批數. [fetchRequest setFetchBatchSize:20]; // 3.建立排序描述符,(ascending:是否升序) NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; // 根據fetchRequest和managedObjectContext來建立aFetchedResultsController對象,並設置緩存名字爲"Master". NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; // 設置aFetchedResultsController的委託對象爲當前類 aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; NSError *error = nil; // 獲取第一批數據 if (![self.fetchedResultsController performFetch:&error]) { // 錯誤處理 NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __fetchedResultsController;}
由於咱們設置了aFetchedResultsController的委託NSFetchedResultsControllerDelegate,就要實現它的方法,幸運的是這些方法看起來都像下面這樣,直接複製粘貼就好了。
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller{ [self.tableView beginUpdates];} - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type{ switch(type) { case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ UITableView *tableView = self.tableView; switch(type) { case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; break; } } - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{ [self.tableView endUpdates];}
- (void)insertNewObject{ // 從NSFetchedResultsController中獲取NSManagedObjectContext對象 NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; // 從NSFetchedResultsController中獲取實體描述 NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; // 在被管理上下文中插入一個新的NSManagedObject NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; // 字段賦值 [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; // 保存被管理對象上下文,這樣剛纔的newManagedObject就被保存了 NSError *error = nil; if (![context save:&error]) { // 錯誤處理. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } }
// 從NSFetchedResultsController中獲取NSManagedObjectContext對象 NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; // 從被管理對象上下文中刪除MO對象 [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; // 保存被管理對象上下文 NSError *error = nil;if (![context save:&error]) { // 錯誤處理 NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort();}
這個刪除對象爲何沒有處理TableView的代碼,由於咱們實現NSFetchedResultsControllerDelegate委託,當對象上下文發生變化時NSFetchedResultsControllerDelegate的實現方法會處理這些事情。