2014年4月29日 星期二

Core Data 概念



The NSFetchedResultsController is a type of controller provided by the Core Data framework that helps manage results from queries. 
NSFetchedResultsController幫我們管理我們要做的查詢
NSManagedObjectContext is a handle to the application’s persistent store that provides a context, or environment, in which the managed objects can exist. 
NSManagedObjectContext 幫我們產生一個存放managed objects的環境,並幫我們處理與persistent store之間的溝通。

//Sample code

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:
self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"]; 
aFetchedResultsController.delegate = self; 
self.fetchedResultsController = aFetchedResultsController; 
我們來了解一下cacheName這個參數的用法:
如果你不想要cache查詢結果,那直接傳nil給他就好。
如果你傳了cacheName給它,那代表它會在下次搜尋之前,先去檢查上一次的cache有沒有相同的值。
如果有找到相同的查詢,就不進行查詢直接取用它;如果不相同,就刪除上次的cache,然後存放這次的查詢結果供下次使用。


the persistent store 通常在操作 SQLite database
而The managed object model 是persistent store的抽象邏輯表現層。


Calling the getter for the delegate’s managedObjectContext starts a chain reaction in which
-(NSManagedObjectContext *)managedObjectContext, calls -(NSPersistentStoreCoordinator *)persistentStoreCoordinator and then in turns calls -(NSManagedObjectModel *)managedObjectModel. The call to managedObjectContext therefore initializes the entire Core Data stack and readies Core Data for use. 

//Delete時,有四個規則
  1. No action 什麼都不做:Does nothing and lets the related objects think the parent object still exists.
  2. Nullify 把每個相關連的物件的父物件設為nil:For each related object, sets the parent object property to null. 
  3. Cascade 把所有相關的物件也一併刪除:Deletes each related object.
  4. Deny 如果仍有相關物件,則禁止delete的動作:Prevents the parent object from being deleted if there is at least one related object. 

//NSFetchedResultsController是用來給UITableView使用的
You use a fetched results controller to efficiently manage the results returned from a Core Data fetch request to provide data for a UITableView object.

//讀取資料
- (NSArray *) readDataWithEntityName:(NSString *)entityName andPredicate:(NSPredicate *)predicate sortDescriptor:(NSString *)sortDescriptorString asceding:(BOOL)isAsceding{
    
    NSManagedObjectContext *context = [_coreData managedObjectContext];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDescription];
    
    // Set example predicate and sort orderings...
    [request setPredicate:predicate];
    
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
                                        initWithKey:sortDescriptorString ascending:isAsceding];
    [request setSortDescriptors:@[sortDescriptor]];
    
    NSError *error;
    NSArray *array = [context executeFetchRequest:request error:&error];
    if (array == nil)
    {
        // Deal with error...
    }
    return array;

}

#pragma mark Save
- (void)saveContext
{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // 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.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

#pragma mark Add
- (void) addNewRecordIntoEntityByName:(NSString *)entityName newObjects:(NSArray *)objects{
    
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:_managedObjectContext];
    
    // If appropriate, configure the new managed object.
    // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
    for (NSDictionary *objectInfo in objects) {
        [objectInfo enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
            [newManagedObject setValue:obj forKey:key];
        }];
    }
    
    
    // Save the context.
    NSError *error = nil;
    if (![_managedObjectContext save:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // 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.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}
#pragma mark Delete
//刪除指定物件
-(void) deleteRecord:(NSManagedObject *)managedObject{
    
    [_managedObjectContext deleteObject:managedObject];
    
    NSError *error = nil;
    if (![_managedObjectContext save:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // 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.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

//恢復上一步
-(void) undoRecord{
    
    [_managedObjectContext.undoManager undo];
    
    NSError *error = nil;
    if (![_managedObjectContext save:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // 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.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

//恢復下一步
-(void) redoRecord{
    
    [_managedObjectContext.undoManager redo];
    
    NSError *error = nil;
    if (![_managedObjectContext save:&error]) {
        // Replace this implementation with code to handle the error appropriately.
        // 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.
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

}

沒有留言:

張貼留言