iOS开发集锦好东西小知识点

(一)CoreData - 基本使用

2017-04-21  本文已影响54人  徊家喂猪

(一)CoreData - 基本使用

@(HTML5秘籍)[Objective-c, iOS, 本地存储]


@一张占位图,心旷神怡的开始阅读吧

题目虽然说的是快速入门,但是CoreData是一门很博大精深的技术,还是不要妄想几天之内能融会贯通。接下来几篇文章会由浅入深,逐步讲解如何使用并掌握CoreData

最近一直在找一些关于日程管理的软件,有一些感觉还不错的,但是总觉得自己想要一些功能都没有,所以干脆就下手自己写一个自己的。由于没有后台服务器做接口,一些数据只能暂时做本地存储。在技术选型的时候做了一些调查,因为之前做过PHP,对SQL印象蛮好的。但是对于一个移动端应用来说,基本不需要大量的存储数据,因此在FMDB,Realm和CoreData之间,选择了苹果的亲儿子CoreData。

[TOC]

封装CoreData管理工具

1. 创建一个自带CoreData代码的工程

在Xcode创建工程的时候,就可以创建一个带有CoreData的工程,在APPdelegate中会生成关于CoreData的代码。


@创建带有CoreData的工程

下图是Xcode7自动创建的CoreData代码,Xcode 8 做了修改,我们先说一下旧版的怎么玩,然后再看看新版怎么弄。

@Xcode 7自动创建的CoreData代码1
@Xcode 7自动创建的CoreData代码2

虽然说已经生成了这些代码,但是还是不能直接用,我们需要将代码重新封装一下。

2. 简单封装CoreData管理类

① 创建一个继承于NSObject的类 LTCoreDataManager

② 写一个单例作为初始化方法

+ (LTCoreDataManager *)shareLTCoreDataManager
{
    static LTCoreDataManager *manager = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[LTCoreDataManager alloc] init];
    });

    return manager;
}

③ 将自动生成的代码粘贴到 LTCoreDataManager.m 中

④ 在 LTCoreDataManager.h 中加入方法声明

+ (LTCoreDataManager *)shareLTCoreDataManager;

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

⑤ 注意:应在 LTCoreDataManager.h 中引入 <CoreData/CoreData.h>

创建CoreData模型文件

1.构建模型文件

在创建工程的时候,如果选择了使用CoreData,Xcode会自动生成一个模型文件,模型文件的后缀为.xcdatamodeld。如果没有选择自动生成模型文件,我们可以手动创建一个模型文件Command + N,选择 Core Data -> Data Model -> Next

@创建好的模板

左侧有三个选项,entitiesfetch requestsconfigurations

2.创建实体

长按左下方的 Add Entity 按钮,会弹出菜Add EntityAdd Fetch RequestAdd Configuration。选择 Add Entity创建一个实体,命名为Plan。如下图所示

@Plan Entity

右侧对应着Attributes(属性)、Relationships(关联关系)、Fetched Properties(获取操作)。
首先,添加两个属性,planName:type 为 String,planId:type 为 Integer64。
需要注意的是,属性的首字母要小写。

关于Type类型的说明

3.添加关联关系

再创建一个实体Task并添加响应的属性。

@添加关联关系

Task添加关联关系,点击Relationships下面的加号,新建一个关联关系,命名为planinverse需要设置好Relationships之后才能设置。

关联关系设置

  1. NSNoActionDeleteRule 删除后没有任何操作,也不会将关联对象的关联属性指向nil。删除后使用关联对象的关联属性,可能会导致其他问题。
  2. NSNullifyDeleteRule 删除后会将关联对象的关联属性指向nil,这是默认值。
  3. NSCascadeDeleteRule 删除当前对象后,会将与之关联的对象也一并删除。
  4. NSDenyDeleteRule 在删除当前对象时,如果当前对象还指向其他关联对象,则当前对象不能被删除。

4.创建托管对象类文件

创建文件
选中后缀名为.xcdatamodeld的模型文件,选择XcodeEditor -> Create NSManagedObject Subclass -> 选择模型文件 -> 选择实体,生成实体对应的托管对象类文件。

@生成的文件

更新文件
当前模型对应的实体发生改变后,需要重新生成模型文件。生成步骤和上面一样,主要是替换Category文件,托管对象文件不会被替换。生成文件时不需要删除,直接替换文件。

增删改查操作

1.插入操作

// 创建托管对象,并指明创建的托管对象所属实体名
Plan *planObj = [NSEntityDescription insertNewObjectForEntityForName:@"Plan" inManagedObjectContext:context];
planObj.planName = @"计划名字";
planObj.planId = [NSNumber numberWithInteger:1];

// 通过上下文保存对象,并在保存前判断是否有更改
NSError *error = nil;
if (context.hasChanges) {
    [context save:&error];
}

// 错误处理
if (error) {
    NSLog(@"CoreData Insert Data Error : %@", error);
}

通过NSEntityDescriptioninsert类方法,生成并返回一个Employee托管对象,并将这个对象插入到指定的上下文中。
managedObjectContext将操作的数据存放在缓存层,只有调用managedObjectContextsave方法后,才会真正对数据库进行操作,否则这个对象只是存在内存中,这样做避免了频繁的数据库访问。

2.删除操作

// 建立获取数据的请求对象,指明对Plan实体进行删除操作
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 创建谓词对象,过滤出符合要求的对象,也就是要删除的对象
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"planName = %@", @"计划名字"];
[request setPredicate:predicate];

// 执行获取操作,找到要删除的对象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];

// 遍历符合删除要求的对象数组,执行删除操作
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    [context deleteObject:obj];
}];

// 保存上下文
if (context.hasChanges) {
    [context save:nil];
}

// 错误处理
if (error) {
    NSLog(@"CoreData Delete Data Error : %@", error);
}

3.更新操作

// 建立获取数据的请求对象,并指明操作的实体为Plan
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 创建谓词对象,设置过滤条件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"planName = %@", @"计划名字"];
request.predicate = predicate;

// 执行获取请求,获取到符合要求的托管对象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    obj.planId = @2;
}];

// 将上面的修改进行存储
if (context.hasChanges) {
    [context save:nil];
}

// 错误处理
if (error) {
    NSLog(@"CoreData Update Data Error : %@", error);
}

4.查询操作

// 建立获取数据的请求对象,指明操作的实体为Plan
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Plan"];

// 执行获取操作,获取所有Plan托管对象
NSError *error = nil;
NSArray<Plan *> *planArr = [context executeFetchRequest:request error:&error];
[planArr enumerateObjectsUsingBlock:^(Plan * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"Plan Name : %@, Id : %@", obj.planName, obj.planId);
}];

// 错误处理
if (error) {
    NSLog(@"CoreData Ergodic Data Error : %@", error);
}

小结一下

看完上面一大堆,其实应该还是不太理解。不过跟着步骤一步步走下来,应该是可以简单实用了。

上一篇下一篇

猜你喜欢

热点阅读