新建工程勾选 "Use CoreData" 你会发现AppDelegate 文件多了一些属性及方法:
- (NSManagedObjectContext*)managedObjectContext
主要用于获取 “被管理的上下文”,将此方法放在AppDelegate 的原因也是显而易见的,那就是需要保持统 一, 既然使用CoreData 那就注意始终使用同一个被管理的上下文,简单的就是同一个对象。
NSManagedObjectContext:被管理的上下文
作用:操作上下文(增删改查)
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
NSPersistentStoreCoordinator : 持久化存储助理
作用:相当于数据库的连接器
- (NSManagedObjectModel *)managedObjectModel
NSManagedObjectModel: 被管理的数据模型
作用:管理实体、维护实体间的关系
通过代码的执行顺序我们发现,通过NSManagedObjectModel 得到 NSPersistentStoreCoordinator 通过 NSPersistentStoreCoordinator 得到 NSManagedObjectContext
NSManagedObjectModel ——>NSPersistentStoreCoordinator——>NSManagedObjectContext
2. 新建Person 实体 同时创建属性name surName
为Person实体生成modal类
3. 创建相关VC
这里就简单介绍关于Person 实体的 新增、修改、删除,所以这里需要再建两个类:PersonTVC(person 实体展示) PeronEditTVC(新增、编辑person)
那UI也很简单,storyboard快速创建相关视图即可,为了方便person 及personEdit是UITableViewController 子类
效果图大致如下:
4、实现相关代码
PersonTVC.h:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface PersonTVC : UITableViewController<NSFetchedResultsControllerDelegate>
//获取结果控制器
@property (strong ,nonatomic) NSFetchedResultsController *fetchedResultController;
//上下文对象
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, assign) BOOL beganUpdates;
@end
NSFetchedResultsController 为系统封装好的 “获取结果控制器”,主要是配合table使用方便,当然你也可以自己去fetch,拿到数组,显示。
NSManagedObjectContext 被管理的上下文,应与Appdelegate里面的上下文对象一致,如何获取就不多说了...
PersonTVC.m
#pragma mark - 初始化fetchResultController
- (void)setupFetchedResultsController
{
// NSBatchUpdateReuqest
// 1 - Decide what Entity you want
NSString *entityName = @"Person"; // Put your entity name here
// 2 - Request that Entity
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:YES
selector:@selector(localizedCaseInsensitiveCompare:)]];
_fetchedResultController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultController.delegate = self;
// 5 - Fetch it
[self performFetch];
}
得到 “获取结果控制器对象”,并将结果按Name 字母排序,也可以不排#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return [[_fetchedResultController sections]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [[[_fetchedResultController sections]objectAtIndex:section]numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"personCell" forIndexPath:indexPath];
Person *person = [self.fetchedResultController objectAtIndexPath:indexPath];
NSString *allName = [NSString stringWithFormat:@"%@ %@",person.name,person.surName];
cell.textLabel.text = allName;
return cell;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException
// Delete the person object that was swiped
Person *personToDelete = [_fetchedResultController objectAtIndexPath:indexPath];
[self.managedObjectContext deleteObject:personToDelete];
[self.managedObjectContext save:nil];
// Delete the (now empty) row on the table
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self performFetch];
[self.tableView endUpdates];
}
}
Table 的代理方法,基本上可以看出,数据源是从 _fetchedResultController 中获取。使用_fetchedResultController的好处还有 它实现了自动数据的自动监听回调,我们能够及时根据数据变化来刷新table。
_fetchedResultController 的代理方法实现
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
_beganUpdates = YES;
}
- (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;
default:
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if (_beganUpdates) [self.tableView endUpdates];
}
可以看出这些代理方法能够很好的监听每个状态的变化,这样我们不必自己去实现监听。
PersonEditTVC
该类主要用于新增,和修改person 对象,所以定义好type 来区分,该类的重点在save 方法的实现
- (IBAction)saveEditPersonClick:(id)sender {
if(_personType == personTypeAdd)
{
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:_managedObjectContext];
if(_nameField.text.length>0&&_surNameField.text.length>0)
{
person.name = _nameField.text;
person.surName = _surNameField.text;
}
}
else if(_personType == personTypeEidt)
{
_currentPerson.name = _nameField.text;
_currentPerson.surName = _surNameField.text;
}
[_managedObjectContext save:nil];
[self.navigationController popViewControllerAnimated:YES];
}
可以看到新增或修改的对象都要是当前上下文_managedObjectContext 的对象,修改或添加后只需调用_managedObjectContext save 即可。当上下文数据有变化时在PersonTVC 中 NSFetctchedResultsControllerDelegete 方法就会执行。实现table 实时刷新。
同样这里实现了新增,修改,同样还有删除。为了方便,直接在PersonTVC 上实现左滑删除。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.tableView beginUpdates]; // Avoid NSInternalInconsistencyException
// Delete the person object that was swiped
Person *personToDelete = [_fetchedResultController objectAtIndexPath:indexPath];
[self.managedObjectContext deleteObject:personToDelete];
[self.managedObjectContext save:nil];
// Delete the (now empty) row on the table
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self performFetch];
[self.tableView endUpdates];
}
}
可以看出,同样也是拿到_fetchedResutController 中的具体对象,然后在上下文_managedObjectContext 中删除。
——————————————————————————
这里简单介绍了CoreData的基本使用方法,有人说用sqlite+FMDB 效果好,也有人支持用CoreData,下篇介绍coreData 与 sqlite 的差异及性能对比。