`
jishublog
  • 浏览: 868919 次
文章分类
社区版块
存档分类
最新评论

数据持久化方法——Core Data

 
阅读更多

概述


Core Data是一种用来解决应用中数据持久化问题的技术。作为一个Cocoa框架,首次在Mac OS X 10.4 Tiger与iOS 3.0系统中出现。它允许按照实体-属性-值模型组织数据,并以XML,二进制文件或SQLite数据文件的格式将其串行化。Core Data允许用户使用代表实体和实体间关系的高层对象来操作数据。它也可以管理串行化的数据,提供对象生存期管理与object graph管理,包括存储。Core Data直接与SQLite交互,避免开发者使用原本的SQL语句。
CoreData的核心概念是托管对象。托管对象是由Core Data管理的简单模型对象,但必须是NSManagedObject类或者其子类的实例。托管对象模型包含一些应用程序托管对象实体的描述,描述中包括属性,关系等。

Core Data中常用的类




Core Data 的初步建立

首先导入框架


创建模型编辑器


这里我想建立三个实体,分别是Car,User和Dealer 在创建好实体后再分别添加属性


高亮选择后可以自动创建对应的类文件


然后我们可以从Style模式里看到我们建立的实体的ER图


建立模型对象类

为了方便管理和使用模型对象,我把有关方法统一建立在了CarModel类中

后面涉及到的主要有:
@property (nonatomic, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext;

- (NSURL *)dataStoreURL;
- (Car *)makeNewCar;
- (NSArray *)carListAfterFetch;

返回数据存储的URL函数

- (NSURL *)dataStoreURL
{
    static NSString *fileName = @"Car.sql";
    NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];    
    NSString *filePath = [docDir stringByAppendingPathComponent:fileName];
    NSURL *fileURL = [NSURL fileURLWithPath:filePath];
    
    return fileURL;
}


数据模型NSManagedObjectModel


- (NSManagedObjectModel *)managedObjectModel
{
    if (_managedObjectModel)
    {
        return _managedObjectModel;
    }
    _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
    
    return _managedObjectModel;
}

使用持久化存储协调器,链接到数据模型


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator)
    {
        return _persistentStoreCoordinator;
    }
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSError *error;
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                   configuration:nil
                                                             URL:[self dataStoreURL]
                                                         options:nil
                                                           error:&error])
    {
        NSLog(@"Error: %@", error);
    }
    
    return _persistentStoreCoordinator;
}


建立托管对象上下文,记录对象图的所有变化。在一些时候,可以执行抓取数据信息并进行检索等等。


- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext)
    {
        return _managedObjectContext;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] init];
    [_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
    return _managedObjectContext;
}


一个创建汽车实例的方法


- (Car *)makeNewCar
{
    Car *newCar = [NSEntityDescription insertNewObjectForEntityForName:@"Car"
                                                inManagedObjectContext:[self managedObjectContext]];
    return newCar;
}


检索数据方法,返回一个数组储存目前存在的实例的信息


- (NSArray *)carListAfterFetch
{
    NSError *error;
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Car" inManagedObjectContext:[self managedObjectContext]];
    fetchRequest.entity = entity;
    
    NSArray *listOfCars = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
    
    return listOfCars;
}

测试

在APPDelegate.m里对主要的方法进行了简单的使用

    CarModel *carModel = [[CarModel alloc] init];
    NSManagedObjectContext *carContext = [carModel managedObjectContext];
    
    Car *car1 = [carModel makeNewCar];
    car1.brand = @"BMW";
    car1.type = @"SUV";
    
    [carContext save:nil];
    
    NSArray *listOfCars = [carModel carListAfterFetch];
    
    [listOfCars enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"CarInList[%i] : %@", idx, [obj brand]);
    }];
    
    Car *rollbackCar = [listOfCars objectAtIndex:0];
    rollbackCar.brand = @"AUDI";
    
    if ([carContext hasChanges]) {
        [carContext rollback];
    }
    
    listOfCars = [carModel carListAfterFetch];
    
    [listOfCars enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        NSLog(@"CarInList[%i] : %@", idx, [obj brand]);
    }];
    
    [carContext deleteObject:car1];
    [carContext save:nil];
    
    listOfCars = [carModel carListAfterFetch];
    
    if ([listOfCars count] == 0) {
        NSLog(@"NULL");
    }
    else {
        [listOfCars enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            NSLog(@"CarInList[%i] : %@", idx, [obj brand]);
        }];
    }

打印的结果是
2013-08-01 21:46:14.860 CoreDataTest[721:c07] CarInList[0] : BMW
2013-08-01 21:46:14.862 CoreDataTest[721:c07] CarInList[0] : BMW
2013-08-01 21:46:14.864 CoreDataTest[721:c07] NULL


这里使用了上下文的存储 删除 读取 回文(rollback)方法
Core Data中还有好多高级方法,如redo/undo等(重做,撤销)。

总结


Core Data看起来比使用SQL语句操作数据更快捷和对象化。但是也有很多喜欢写SQL语句的工程师,更偏爱直接操纵数据库。
总结起来Core Data的优点还是很多:
App升级之后数据库字段或者表有更改会导致crash,CoreData的版本管理和数据迁移变得非常有用,手动写sql语句操作还是麻烦一些。
CoreData不光能操纵SQLite,CoreData和iCloud的结合也很好,如果有这方面需求的话优先考虑CoreData。
提供NSFetchedResultsController 类用于管理表视图的数据。即将Core Data的持久化存储显示在表视图中,并对这些数据进行管理:增、删,改。
管理undo/redo操作。
检查托管对象的属性值是否正确。

虽然现在还不能直接设置主键,但是其已经足够强大,也相信以后将会更加便捷。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics