iOS 即时通讯(三):CoreData的使用

说道IM,就不得不说一下iOS的数据存储方式,不知道大家有没有发现,当你换了手机,在微信上重新登录你的账号,你的聊天记录全都不见了,而QQ则不是这样,这是为什么呢?大家肯定能想到,QQ是在服务端存储的,而微信是在本地存储的。所以这里就牵扯到了iOS的数据持久化方式。今天我就介绍其中的一种:CoreData。

概念:

什么是CoreData呢?CoreData是个框架,并不是数据库,它使开发者可以把数据当做对象来操作,而不在乎数据在磁盘中的存储方式。类似于Hibernate,CoreData提供了一种对象-关系映射(ORM)的机制,避免了开发者去书写SQL语句,将其面向对象化。由CoreData提供的数据对象叫做托管对象(Managed Object),而CoreData本身则位于你的应用程序和持久化存储区(Persistent Store)之间。为了把数据从托管对象映射到持久化存储区中,CoreData需要使用托管对象模型。所有的托管对象都必须位于托管对象上下文(Managed Object Context)里面,而托管对象上下文又位于高速的易失性存储器里面,也就是位于RAM中。

为什么需要有托管对象上下文呢?原因之一就是磁盘与RAM之间传输数据时会有开销。磁盘读写速度比RAM慢得多,所以不应该频繁地访问它。有了托管对象上下文,就可以非常迅速地获取到了。但它的缺点在于,开发者必须在托管对象上下文上面定期调用save方法,以将变更后的数据写回磁盘。托管对象上下文的另一个功能是记录开发者对托管对象所做的修改,以提供完整的撤销和重做支持。

项目中添加Core Data:

添加CoreData有2种方式:
(1)新建项目的时候勾选Use Core Data,如下图,这样系统就会自动为你创建Core Data相关的文件。

iOS 即时通讯(三):CoreData的使用_第1张图片
新建项目时勾选Use Core Data

(2)如果项目开始时没有勾选Use Core Data,也没有关系,可以手动添加。
a.新建Data Model( 相当于数据库)文件,操作过程如下图
iOS 即时通讯(三):CoreData的使用_第2张图片
iOS 即时通讯(三):CoreData的使用_第3张图片

b.新建实体(Entity,相当于数据库中的表),这个过程相当于在数据库中新建表,然后在表中添加字段。

iOS 即时通讯(三):CoreData的使用_第4张图片

c.完成前2步之后,数据库、数据库中的表以及表中的字段都已经建好了,之前我们已经介绍过了,Core Data提供了一种对象-关系映射(ORM),所以我们还需要新建一个对象与之对象。 (这里有个小地方需要注意一下,Xcode8 Core Data里面没有了NSManagedObject subclass这个选项,需要在菜单栏的Editor->Create NSManagedObject Subclass进行创建)

iOS 即时通讯(三):CoreData的使用_第5张图片

iOS 即时通讯(三):CoreData的使用_第6张图片

ok,Core Data创建工作已经完成了,下面就来看一下怎么使用。

基本用法:

Core Data其实是对SQLite进行的封装,所以基本用法无外乎CURD(增删改查),下面我们就直接上代码,来看一下Core Data的基本用法。
(1)在viewDidLoad中添加如下代码进行初始化。

    //1、创建模型对象
    //获取模型路径
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Company" withExtension:@"momd"];
    //根据模型文件创建模型对象
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    
    //2、创建持久化助理
    //利用模型对象创建助理对象
    NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    
    //数据库的名称和路径
    NSString *docStr = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *sqlPath = [docStr stringByAppendingPathComponent:@"Employee.sqlite"];
    NSLog(@"path = %@", sqlPath);
    NSURL *sqlUrl = [NSURL fileURLWithPath:sqlPath];
    
    //设置数据库相关信息
    [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlUrl options:nil error:nil];
    
    //3、创建上下文
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    //关联持久化助理
    [context setPersistentStoreCoordinator:store];
    
    _context = context;

(2)添加数据

// 添加员工
- (IBAction)addEmployee:(id)sender {
    Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:_context];
    emp.name = _nameTxt.text;
    emp.birthday = [NSDate date];
    emp.age = [_ageTxt.text intValue];
    // 保存
    NSError *error = nil;
    [_context save:&error];
    if (error) {
        NSLog(@"保存失败:%@", error);
    } else {
        NSLog(@"保存成功");
    }
}

(3)删除数据

// 删除员工
- (IBAction)deleteEmployee:(id)sender {
    // 1.NSFetchRequest 抓取请求
    NSFetchRequest *fetchRequest = [Employee fetchRequest];
    // 2.过滤
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"Lisi"];
    fetchRequest.predicate = pre;
    // 3.执行抓取请求
    NSError *error = nil;
    NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
    if (error) {
        NSLog(@"获取失败!%@", error);
    } else {
        if (employees.count == 0) {
            NSLog(@"没有查询到该员工!");
            return;
        }
        for (Employee *emp in employees) {
            [_context deleteObject:emp];
        }
        [_context save:&error];
        if (error) {
            NSLog(@"删除失败:%@", error);
        } else {
            NSLog(@"删除成功");
        }
    }
}

(4)修改数据

// 更新员工
- (IBAction)updateEmployee:(id)sender {
    // 1.NSFetchRequest 抓取请求
    NSFetchRequest *fetchRequest = [Employee fetchRequest];
    // 2.过滤
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"zhangsan"];
    fetchRequest.predicate = pre;
    // 3.执行抓取请求
    NSError *error = nil;
    NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
    if (error) {
        NSLog(@"获取失败!%@", error);
    } else {
        if (employees.count == 0) {
            NSLog(@"没有查询到该员工!");
            return;
        }
        for (Employee *emp in employees) {
            emp.age = 100;
        }
        [_context save:&error];
        if (error) {
            NSLog(@"更新失败:%@", error);
        } else {
            NSLog(@"更新成功");
        }
    }
}

(5)查询数据

// 查询员工
- (IBAction)loadEmployee:(id)sender {
    // 1.NSFetchRequest 抓取请求
    NSFetchRequest *fetchRequest = [Employee fetchRequest];
    // 2.过滤
//    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@", @"zhangsan"];
//    fetchRequest.predicate = pre;
    // 3.排序
    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"age" ascending:NO]];
    // 4.执行抓取请求
    NSError *error = nil;
    NSArray *employees = [_context executeFetchRequest:fetchRequest error:&error];
    if (error) {
        NSLog(@"获取失败!%@", error);
    } else {
        for (Employee *emp in employees) {
            NSLog(@"名字:%@, 年龄:%d, 生日:%@", emp.name, emp.age, emp.birthday);
        }
    }
}

代码里都有详细的注释,我就不过多解释了,也不是很难,只要理解了Core Data的概念,其他的都还算比较好理解。

你可能感兴趣的:(iOS 即时通讯(三):CoreData的使用)