iPhone開發之CoreData(基礎篇)

經過上一篇iPhone開發之SQLite的學習,基本學會了 SQLite在iPhone中的使用,這時候我就在找有沒有SQLite的封裝類,這樣能夠避免本身重複地SQLite的封裝代碼,Google一下,找 到幾個objc-sqlite、FMDB等,還有一些其它不知名的封裝庫,官方也提供了CoreData框架來提供完整的對象持久化存儲方案,仍是有必要 要學習一下。sql

基本概念

在CoreData有一些概念剛學習的時候不是很容易理解,仍是要單獨拿出來來梳理一下,這樣學後面的內容不會感受吃力。數據庫

coredata terminology

圖1

從圖1中咱們能夠看到,在數據庫結構中的一些術語,在這裏會有對應,但不是所有。xcode

  • ♥ 表結構:NSEntityDescription
  • ♥ 表記錄:NSManagedObject

coredata aps

圖2

從圖2中咱們能夠看到一些數據庫操做方面的一些術語緩存

  • ♥ 數據庫存放方式:NSPersistentStoreCoordinator(持久化存儲協調者)
  • ♥ 數據庫操做:NSManagedObjectContext(被管理的對象上下文)

還有一些類NSManagedObjectModel、NSFetchRequest什麼的,具體項目就會有體會,下面來實戰一下。框架

新建一個項目,項目模板基於「Master-Detail Application」,點擊「Next」按鈕,項目命名爲「SimpleCoreData」,並勾選「Use Core Data」,點擊「Next」,選擇項目保存的目錄,點擊「Create」按鈕,項目建立完畢。函數

SimpleCoreData SimpleCoreData xcodeproj

圖3

代碼分析

比之前建立的簡單項目多了很多代碼,還有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

  • ♥ -tableView:(UITableView *)tableView cellForRowAtIndexPath:
  • ♥ -configureCell:atIndexPath:
  • ♥ -fetchedResultsController

最後是從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的實現方法會處理這些事情。

相關文章
相關標籤/搜索