iOS开发CoreData的简单使用

1、简介

  CoreData是iOS5后,苹果提供的原生的用于对象化管理数据并且持久化的框架。iOS10苹果对CoreData进一步进行了封装,而且效率更高!相关类的简单介绍:

NSManagedObjectModel    模型对象:添加实体的属性,建立属性之间的关系
NSPersistentStoreCoordinator    数据库的助理:设置数据存储的名字,位置,存储方式,和存储时机
NSManagedObjectContext  生成上下文,关联数据库助理,插入数据,查询数据,删除数据,更新数据
NSPersistentContainer (iOS10之后才能使用)一个容器,封装了应用程序中的CoreData Stack(核心数据栈堆)

 

2、创建CoreData

  1)创建CoreData操作源文件 xxxx.xcdatamodeld

  方法一:创建工程时直接勾选 Use Core Data 选项

  方法二:手动创建

    通过New File --->>iOS (Core Data) Data Model路径创建!

  2)创建实体(model)

    通过导航栏Editor--->>Create NSManagedObject Subclass--->>选择表 --->> 选择model

 

 》》》》》》

 

  然后会生成四个文件如图所示:

  注意:1、右边可以选择创建实体类语言Objective-C或者Swift;

       2、创建之后工程报错CoreData手动创建托管对象子类时报错解决方法;

 

3、简单使用CoreData

  方法一:在iOS10之前使用详情

    自动创建CoreData时,在AppDelegate.m文件中有系统封装的方法如下:(手动创建就是把方法复制一遍)

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    [self saveContext];
}
#pragma mark - Core Data stack

//NSManagedObject(被管理的数据记录)
//数据库中的表格记录

//NSEntityDescription(实体结构)
//相当于表格结构

//NSFetchRequest(数据请求)
//相当于查询语句

//.xcdatamodel文件,用数据模型编辑器编辑
//编译后为.momd或.mom文件

//存储路径
- (NSURL *)applicationDocumentsDirectory {
    NSLog(@"===%lu",(unsigned long)NSDocumentDirectory);
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

//创建模型对象
//作用:添加实体的属性,建立属性之间的关系
//操作方法:视图编辑器,或代码
- (NSManagedObjectModel *)managedObjectModel {
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataTest" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

//创建数据库助理
//作用:设置数据存储的名字,位置,存储方式,和存储时机
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataTest.sqlite"];
    NSError *error = nil;
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
        NSMutableDictionary *dict = [NSMutableDictionary dictionary];
        dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
        dict[NSLocalizedFailureReasonErrorKey] = failureReason;
        dict[NSUnderlyingErrorKey] = error;
        error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    return _persistentStoreCoordinator;
}

//生成上下文,关联数据库助理
//作用:插入数据,查询数据,删除数据,更新数据
- (NSManagedObjectContext *)managedObjectContext {
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (!coordinator) {
        return nil;
    }
    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    return _managedObjectContext;
}

#pragma mark - Core Data Saving support
//保存
- (void)saveContext {
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        NSError *error = nil;
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

    具体的增加、删除、修改、查找数据操作如下:(一般情况下使用CoreData都会自己把上面方法封装,组成一个CoreData的工具类)

//添加一条数据
- (void)addData{
    Student *newEintity = [NSEntityDescription insertNewObjectForEntityForName:Model_Name inManagedObjectContext:self.managedObjectContext];
    newEintity.name = @"张三";
    newEintity.age = @"13";
    [self saveContext];
}

//删除一条数据
- (void)deleData{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name];
    NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"];
    request.predicate = predic;
    NSArray *arr = [self.managedObjectContext executeFetchRequest:request error:nil];
    if (arr.count>0) {
        [self.managedObjectContext deleteObject:arr.firstObject];
        [self saveContext];
    }
}
//删除和修改数据时先查找
//改变一条数据
- (void)exchangeData{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name];
    NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"];
    request.predicate = predic;
    NSArray *arr = [self.managedObjectContext executeFetchRequest:request error:nil];
    if (arr.count>0) {
        Student *objc = (Student *)arr.firstObject;
        objc.name = @"李四";
        objc.age = @"43";
        [self saveContext];
    }
}

  方法二:iOS10之后,苹果添加了一个NSPersistentContainer类,将之前方法进行了封装。这时候AppDelegate.m中的方法只有:

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    // Saves changes in the application's managed object context before the application terminates.
    [self saveContext];
}


#pragma mark - Core Data stack

@synthesize persistentContainer = _persistentContainer;

- (NSPersistentContainer *)persistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"TestCoreData"];
            [_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 *context = self.persistentContainer.viewContext;
    NSError *error = nil;
    if ([context hasChanges] && ![context 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)addData{
    Student *newEintity = [NSEntityDescription insertNewObjectForEntityForName:Model_Name inManagedObjectContext:self.delegate.persistentContainer.viewContext];
    newEintity.name = @"张三";
    newEintity.age = @"13";
    [self.delegate saveContext];
}

//删除一条数据
- (void)deleData{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name];
    NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"];
    request.predicate = predic;
    NSArray *arr = [self.delegate.persistentContainer.viewContext executeFetchRequest:request error:nil];
    if (arr.count>0) {
        [self.delegate.persistentContainer.viewContext deleteObject:arr.firstObject];
        [self.delegate saveContext];
    }
}
//删除和修改数据时先查找
//改变一条数据
- (void)exchangeData{
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:Model_Name];
    NSPredicate *predic = [NSPredicate predicateWithFormat:@"name = %@",@"张三"];
    request.predicate = predic;
    NSArray *arr = [self.delegate.persistentContainer.viewContext executeFetchRequest:request error:nil];
    if (arr.count>0) {
        Student *objc = (Student *)arr.firstObject;
        objc.name = @"李四";
        objc.age = @"43";
        [self.delegate saveContext];
    }
}

 

4、关于iOS10新类NSPersistentContainer的简介

//版本要求
API_AVAILABLE(macosx(10.12),ios(10.0),tvos(10.0),watchos(3.0))
@interface NSPersistentContainer : NSObject {
#if (!__OBJC2__)
//将之前的属性直接封装
@private
    id _name;
    NSManagedObjectContext *_viewContext;
    id _storeCoordinator;
    id _storeDescriptions;
#endif
}

/**类方法创建NSPersistentContainer
* name:表示保存的数据库文件名称
* 使用此方法创建NSPersistentContainer,默认模型文件名称为name
*/
+ (instancetype)persistentContainerWithName:(NSString *)name;
/**类方法创建NSPersistentContainer
* name:表示保存的数据库文件名称
* model:对象管理模型
*/
+ (instancetype)persistentContainerWithName:(NSString *)name managedObjectModel:(NSManagedObjectModel *)model;

//返回沙盒中存储数据库的文件夹URL路径,这个文件夹是动态创建的(Library->Application Support)
+ (NSURL *)defaultDirectoryURL;

//当前NSPersistentContainer容器的名称
@property (copy, readonly) NSString *name;
//自动生成的管理对象上下文,这个上下文默认的操作类型是NSMainQueueConcurrencyType主线程
@property (strong, readonly) NSManagedObjectContext *viewContext;
//对象管理模型
@property (strong, readonly) NSManagedObjectModel *managedObjectModel;
//存储调度器
@property (strong, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
//存储器描述数组
@property (copy) NSArray<NSPersistentStoreDescription *> *persistentStoreDescriptions;

// 和上面初始化一样
- (instancetype)initWithName:(NSString *)name;
- (instancetype)initWithName:(NSString *)name managedObjectModel:(NSManagedObjectModel *)model NS_DESIGNATED_INITIALIZER;

//加载存储器,此方法必须要调用,否则无法存储数据
//block中NSPersistentStoreDescription用于描述生成的存储器信息,如:数据库文件路径、存储类型等  NSError用于描述加载存储器是否成功或失败信息
- (void)loadPersistentStoresWithCompletionHandler:(void (^)(NSPersistentStoreDescription *, NSError * _Nullable))block;

//返回一个基于多线程的管理对象上下文,我们无需关心多线程的内部实现以及线程安全,由NSPersistentContainer新创建一个
//调用这个方法之后,对返回的上下文做一些数据的处理都是在子线程中完成的,可以用于处理对数据库进行大量数据操作的场景
- (NSManagedObjectContext *)newBackgroundContext NS_RETURNS_RETAINED;

//使用存储调度器快速在多线程中操作数据库,效率非常高
- (void)performBackgroundTask:(void (^)(NSManagedObjectContext *))block;

 

posted @ 2018-01-16 15:43  ForeverGuard  阅读(693)  评论(0编辑  收藏  举报