CoreData

CoreData概念

CoreData是一种OR-Mapping思想,O代表对象Object,R代表Relationship,Mapping代表映射,总结起来就是对象关系映射其实就是把对象的属性和表中的字段自动映射。CoreData本质还是数据库,只不过它具有面相对象的特性,不关注二维表结构,是纯对象的数据库操作方式。

初始化Core Data Stack

Core Data Stack相当于一个「工作台」,是一切操作的所在地。

不过由于iOS10新引进了NSPersistentContainer类,然后新建项目又可以选择勾选Core Data与否。所以情况变得稍稍有点复杂。

这里分三种情况:
1、在既有项目(只需支持iOS10)初始化Core Data Stack
2、在既有项目(需兼容iOS8、9、10等系统)初始化Core Data Stack
3、新建项目时直接勾选了Core Data

  • 情况1:在既有项目添加Core Data功能(只需支持iOS10)
    由于iOS10引进了NSPersistentContainer,如果单单只支持iOS10系统,初始化Core Data Stack相比以前简单很多。
// 我们先声明了一个NSPersistentContainer类型的属性:persistentContainer,在适合的时间调用initWithName:对其初始化
// 这里的Name参数,需要和后续创建的.xcdatamodeld模型文件名称一致。
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"MoveBand"];

// 调用loadPersistentStoresWithCompletionHandler:方法,完成Core Data Stack的最中初始化。
// 如果不能初始化成功,在Block回调中打印错误,方便调试
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription * _Nonnull description, NSError * _Nullable error) {

    if (error != nil) {
        NSLog(@"Fail to load Core Data Stack : %@", error);
        abort();
    }
    else {
        ...
    }
}];

就两步:
(1) 初始化NSPersistentContainer对象;
(2) 调用NSPersistentContainerloadPersistentStoresWithCompletionHandler:完成初始化。

  • 情况2:在既有项目初始化Core Data Stack(需兼容iOS8、9、10等系统)
    因为NSPersistentContainer不兼容iOS10之前的系统。所以,如果你已经用了NSPersistentContainer初始化了Core Data Stack,但同时也要兼容iOS8、9等系统,就需要在代码中检查,如果是旧的系统,就需要用旧的方法初始化Core Data Stack了。示例如下:
- (instancetype)init
{
    self = [super init];
    if (self) {
        NSInteger majorVersion = [NSProcessInfo processInfo].operatingSystemVersion.majorVersion;
        if (majorVersion < 10) {
            // iOS10以下的系统, 用旧有的方法初始化Core Data Stack
            [self initializeCoreDataLessThaniOS10];
        }
        else {
            // iOS10的系统, 用新的方法(详见上面介绍的情况1)
            [self initializeCoreData];
        }
    }
    return self;
}


- (void)initializeCoreDataLessThaniOS10 {
    // Get managed object model(拿到模型文件,也就是.xcdatamodeld文件(我们会在初始化完Core data Stack后创建))
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MoveBand" withExtension:@"momd"];
    NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    NSAssert(mom != nil, @"Error initalizing Managed Object Model");

    // Create persistent store coordinator(创建NSPersistentStoreCoordinator对象(需要传入上述创建的NSManagedObjectModel对象))
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];

    // Creat managed object context(创建NSManagedObjectContext对象(_context是声明在.h文件的属性——因为其他类也要用到这个属性))
    _context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];

    // assgin persistent store coordinator(赋值persistentStoreCoordinator)
    _context.persistentStoreCoordinator = psc;

    // Create .sqlite file(在沙盒中创建.sqlite文件)
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSURL *documentsURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    NSURL *storeURL = [documentsURL URLByAppendingPathComponent:@"DataModel.sqlite"];

    // Create persistent store(异步创建NSPersistentStore并add到NSPersistentStoreCoordinator对象中,作用是设置保存的数据类型(NSSQLiteStoreType)、保存路径、是否支持版本迁移等)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // 用于支持版本迁移的参数
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                 [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
        NSError *error = nil;
        NSPersistentStoreCoordinator *psc = _context.persistentStoreCoordinator;

        // 备注,如果options参数传nil,表示不支持版本迁移
        NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType
                                                     configuration:nil
                                                               URL:storeURL
                                                           options:options
                                                             error:&error];
        NSAssert(store != nil, @"Error initializing PSC: %@\n%@", [error localizedDescription], [error userInfo]);
    });
}
  • 情况3:直接勾选Core Data

创建项目时,如果直接勾选Core Data复选框,项目模版会在AppDelegate类中直接帮你初始化好Core Data Stack,自动创建和上面情况1类似的代码(Xcode8)

在AppDelegate.h文件

#import 
// 导入了CoreData框架
#import 

@interface AppDelegate : UIResponder 

@property (strong, nonatomic) UIWindow *window;

// 在.h文件声明一个NSPersistentContainer类型的属性(为了让其他类可以调用)
@property (readonly, strong) NSPersistentContainer *persistentContainer;

// 声明了一个保存数据的方法
- (void)saveContext;

@end

在AppDelegate.m文件

@implementation AppDelegate
#pragma mark - Core Data stack
@synthesize persistentContainer = _persistentContainer;

- (NSPersistentContainer *)persistentContainer {
    @synchronized (self) {
        if (_persistentContainer == nil) {
            // 实例化NSPersistentContainer对象。
            // 注意:参数传入的名称,就是.xcdatamodeld文件名称(两者需要一直)(勾选Core Data后,会自动创建一个.xcdatamodeld文件)
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"CoreDataTestUseCoreData"];

            // 加载persistent stores,实现最终的Core Data stack的创建
            [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                // 如果有错误,打印出来
                if (error != nil) {
                    NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                    abort();
                }
            }];
        }
    }

    return _persistentContainer;
}

#pragma mark - Core Data Saving support

- (void)saveContext {
    // 注意这句,NSManagedObjectContext对象,是通过上面创建的NSPersistentContainer对象的属性viewContext获取的,无需自己初始化(iOS10之前要自己初始化)
    NSManagedObjectContext *context = self.persistentContainer.viewContext;

    NSError *error = nil;
    // 保存数据,直接用的是NSManagedObjectContext的save:方法,很简单。
    if ([context hasChanges] && ![context save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, error.userInfo);
        abort();
    }
}

系统帮我们创建了一个NSPersistentContainer实例,以及一个saveContext方法。(并且已经帮我们创建了.xcdatamodeld模型文件)

你可能感兴趣的:(CoreData)