美文网首页
Core Data基本使用(附两表关联Demo)

Core Data基本使用(附两表关联Demo)

作者: cocoaCoffee | 来源:发表于2018-10-16 20:59 被阅读0次

    前言

       对于许多应用来说,需要将本地保存和获取的数据持久化用在其他会话中。从ios3.0开始,Core Data就负责完成这项工作。Core Data是一个非常强大的对象数据库,提供了非常健壮的数据存储和管理功能,和java EE的MyBetis有点类似,都是对数据持久化封装的框架,Core Data是对SQLite的封装,是SQLite的轻量版

    特性

    • 使用可视化模型编辑器模块化数据对象
    • 对象架构变化时自动处理和手动处理间转换的工具
    • 在对象间建立关系(一对一、一对多、多对多)
    • 在不同的文件和文件格式中保存数据
    • 对象特性的有效性验证
    • 查询和排序数据
    • 数据的延时加载
    • 同iOS表视图和集合视图紧密交互
    • 通过提交和撤销功能管理相关对象的变化

    Demo描述

      有两张表,这样既可以学会基础的增删查改,也可以知道多表之间的操作,下面可能比较基础

    创建项目

    image.png

    这个我们可以先别选,因为做项目的时候你怎么知道要用Core Data,然后我们自己手动创建一个文件,command+N


    image.png

    创建成功就会多出一个.xcdatamodeld的文件,这个就是模型文件,注意这不是底层数据库,只是数据库的映射吧,点击这个文件看看


    Snip20181016_2.png

    点击Add Entity创建两个实体(实体名称首字母必须大写),学生实体和课程实体,学生有三个属性,课程有两个属性,关系是多对多关系,一个学生可以有多门课程,一门课程可以多个学生学习,先看下那个lentstudent这个相当于外键的名称吧,第二个就是关联哪张表,第三个就是逆,即你在关联哪张表的关联名称,也就是说你在Cousre实体关联Student实体的关联名称是lentstudent,那个Inverse是lentcourse,那么你在在Student实体关联Cousre实体的关联名称是lentsourse

    选中关系看右边 image.png

    to many就是对多咯,你想要多对多就是两张表都设置成to many就多对多了

    把这些都搞完了,就要创建实体模型的类了,就相当于plist文件,你要创建一个模型类。

    core data创建实体的模型类,xcode会帮你做,直接点就行了,选中
    .xcdatamodeld文件,然后看图


    image.png
    image.png

    点完后就会多出这几个实体类,你想用那个实体引用头文件就行


    image.png

    接下来我们去storyboard上拉四个按钮,简单地修改他的约束,在把他们的单击事件拉到控制器

    image.png
    image.png

    接下来记住几个Core Data类名

    • NSManagedObjectModel
      描述了数据模型的结构信息(被管理的数据模型,数据结构)
    • NSPersistentStoreCoordinator
      数据持久层和内存对象模型的协助器(添加数据库,设置数据存储的名字,位置,存储方式)
    • NSManagedObjectContext
      内存中managedObject对象的上下文(管理对象上下文,持久性存储模型对象,处理数据与应用的交互)
    • NSFetchRequest
      数据请求
    • NSEntityDescription
      表格实体结构

    首先看下Demo的头文件

    image.png

    首先肯定要有coredata的头文件,你要用什么实体(表)就添加什么实体的这个类


    image.png

    第一步 创建数据库

       这里的数据库是指底层的SQLite,这里写个方法,没有直接帮你创建这个名字的sqlite数据库,我们先创建一个管理上下文的对象

     //用来管理上下文的对象
    NSManagedObjectContext * _context;
    

    再写创建数据库的方法

    //创建数据库
    - (void)creatsqlite
    {
    //1、创建模型对象
    //获取模型路径
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" 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:@"sqlite.sqlite"];
    NSLog(@"数据库 path = %@", sqlPath);
    NSURL *sqlUrl = [NSURL fileURLWithPath:sqlPath];
    
    NSError *error = nil;
    //设置数据库相关信息 添加一个持久化存储库并设置存储类型和路径,NSSQLiteStoreType:SQLite作为存储库
    [store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqlUrl options:nil error:&error];
    
    if (error) {
        NSLog(@"添加数据库失败:%@",error);
    } else {
        NSLog(@"添加数据库成功");
    }
    
    //3、创建上下文 保存信息 操作数据库
    
    NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    
    //关联持久化助理
    context.persistentStoreCoordinator = store;
    
    _context = context;
    
    }
    

    这里为什么获取模型文件的时候是momd而不是xcdatamodeld
    因为初始化必须依赖.momd文件路径,而.momd文件由.xcdatamodeld文件编译而来

    跑一下工程

    image.png

    这个路径就会多出一个叫sqlite的数据库,自己可以根据给出的路径去找下,查看隐藏文件夹快捷键shift+cmmand+.

    第二步 插入数据

    //增
    - (IBAction)insertData {
    
    // 1.根据Entity名称和NSManagedObjectContext获取一个新的继承于NSManagedObject的子类Student
    
    //  2 根据表Course中的键值,给NSManagedObject对象赋值
    
    Course *course1 = [NSEntityDescription
                       insertNewObjectForEntityForName:@"Course"
                       inManagedObjectContext:_context];
    course1.name = @"iOS";
    course1.creatdate = [NSDate date];
    
    Course *course2 = [NSEntityDescription
                       insertNewObjectForEntityForName:@"Course"
                       inManagedObjectContext:_context];
    course2.name = @"Android";
    course2.creatdate = [NSDate date];
    
    //  3 同上操作
    
    Student *student1 = [NSEntityDescription
                         insertNewObjectForEntityForName:@"Student"
                         inManagedObjectContext:_context];
    student1.name = @"张三";
    student1.birthday = [NSDate date];
    //student1.lentcourse = course1;
    [student1 addLentcourseObject:course1];
    
    Student *student2 = [NSEntityDescription
                         insertNewObjectForEntityForName:@"Student"
                         inManagedObjectContext:_context];
    student2.name = @"李四";
    student2.birthday = [NSDate date];
    [student2 addLentcourseObject:course2];
    
    
    //   4.保存插入的数据
    NSError *error = nil;
    if ([_context save:&error]) {
        NSLog(@"数据插入到数据库成功");
    }else{
    
        NSLog(@"数据插入到数据库失败, %@",error);
    }
    }
    
    • 注意
      student1.lentcourse = course1这样写不怎么对,我也是看网上有些教程这样写,类型不对,course1是NSSet类型而student1.lentcourse好像是Course类,所以,我们找下Student+CoreDataProperties.h这个类,他提供了一个方法
    -(void)addLentcourseObject:(Course *)value;
    

    这个方法返回才是Course类的

    写完这个方法我们再跑下,看下他有没有添加数据进去了,可以用这个软件看下这个数据库


    image.png

    点击插入


    image.png
    加进来了
    image.png

    第三步 查询数据

    //查
    - (IBAction)queryData {
    //1:FectchRequest 抓取请求对象
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    //2:设置过滤条件  这里我们查询选了iOS课的学生信息
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"ANY lentcourse.name = %@",@"iOS"];
    request.predicate = pre;
    //3:设置排序
    //    NSSortDescriptor *height = [NSSortDescriptor sortDescriptorWithKey:@"height" ascending:YES];
    //    request.sortDescriptors = @[height];
    
    //4:执行请求
    NSArray *message = [_context executeFetchRequest:request error:nil];
    //遍历查询结果
    for (Student *student in message) {
        NSLog(@"名字:%@,生日:%@",student.name,student.birthday);
    }
    
    
    
    }
    
    iOS课程是张三在学习
    • 注意 那个过滤条件前是要加ANY的,等下下面我会给出那些谓词条件,有些教程没加ANY我也不知道他怎么跑起来的

    第四步 删除

    //删
    - (IBAction)deleteData {
    //1:先查询到需要删除的数据(比如这里以删除员工张三的数据为例)
    //1.1:FectchRequest 抓取请求对象
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    //1.2:设置过滤条件
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@",@"张三"];
    request.predicate = pre;
    //1.3执行查询请求
    NSArray *message = [_context executeFetchRequest:request error:nil];
    //2:执行删除操作
    for (Student *student in message) {
        [_context deleteObject:student];
    }
    
    //3:保存
    [_context save:nil];
    }
    

    点击删除,张三没了


    image.png

    第五步 修改

    //改
    - (IBAction)upDateData {
    //1:先查询出需要更新的数据
    //1.1:FectchRequest 抓取请求对象
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Student"];
    //1.2:设置过滤条件
    NSPredicate *pre = [NSPredicate predicateWithFormat:@"name = %@",@"李四"];
    request.predicate = pre;
    //1.3执行查询请求
    NSArray *message = [_context executeFetchRequest:request error:nil];
    
    //2:更新数据
    for (Student *student  in message) {
        student.name = @"王五";
    }
    //3:保存
    [_context save:nil];
    
    }
    
    image.png
    /* 谓词的条件指令
     1.比较运算符 > 、< 、== 、>= 、<= 、!=
     例:@"number >= 99"
    
     2.范围运算符:IN 、BETWEEN
     例:@"number BETWEEN {1,5}"
     @"address IN {'shanghai','nanjing'}"
    
     3.字符串本身:SELF
     例:@"SELF == 'APPLE'"
    
     4.字符串相关:BEGINSWITH、ENDSWITH、CONTAINS
     例:  @"name CONTAIN[cd] 'ang'"  //包含某个字符串
     @"name BEGINSWITH[c] 'sh'"    //以某个字符串开头
     @"name ENDSWITH[d] 'ang'"    //以某个字符串结束
    
     5.通配符:LIKE
     例:@"name LIKE[cd] '*er*'"   // *代表通配符,Like也接受[cd].
     @"name LIKE[cd] '???er*'"
    
     *注*: 星号 "*" : 代表0个或多个字符
     问号 "?" : 代表一个字符
    
    6.正则表达式:MATCHES
     例:NSString *regex = @"^A.+e$"; //以A开头,e结尾
     @"name MATCHES %@",regex
    
     注:[c]*不区分大小写 , [d]不区分发音符号即没有重音符号, [cd]既不    区分大小写,也不区分发音符号。
    
     7. 合计操作
     ANY,SOME:指定下列表达式中的任意元素。比如,ANY     children.age < 18。
     ALL:指定下列表达式中的所有元素。比如,ALL children.age < 18。
     NONE:指定下列表达式中没有的元素。比如,NONE children.age < 18。它在逻辑上等于NOT (ANY ...)。
     IN:等于SQL的IN操作,左边的表达必须出现在右边指定的集合中。比如,name IN { 'Ben', 'Melissa', 'Nick' }。
    
     提示:
     1. 谓词中的匹配指令关键字通常使用大写字母
     2. 谓词中可以使用格式字符串
     3. 如果通过对象的key
     path指定匹配条件,需要使用%K
    
     */
    

    因为才看了网上很多文章写出来的,绝对是取其精华的,有些文章比我的还水,有些观点也是我自己的观点,我也是一名菜鸟,希望有错能指出,相互学习

    最后附上源码地址:Demo Github地址

    相关文章

      网友评论

          本文标题:Core Data基本使用(附两表关联Demo)

          本文链接:https://www.haomeiwen.com/subject/phoxzftx.html