iOS App中数据管理框架Core Data的基本数据操作教程

时间:2021-09-20 14:40:18

nsentitydescription是实体描述对象,它可以类比如数据库中的表,nsentitydescription存放的是表的结构信息。这些类都是一些抽象的结构类,并不存储实际每条数据的信息,具体的数据由nsmanagedobject类来描述,我们一般会将实体类化继承于nsmanagedobject。

xocde工具提供了快捷的实体类化功能,还拿我们一开始创建的班级与学生实体来演示,点击.xcdatamodeld文件,点击xcode工具上方导航栏的editor标签,选择creat nsmanagedobject subclass选项,在弹出的窗口中勾选要类化的实体,如下图:

iOS App中数据管理框架Core Data的基本数据操作教程

iOS App中数据管理框架Core Data的基本数据操作教程

这时,xcode会自动为我们创建一个文件,这些文件中有各个类中属性的声明。

一、创建一条数据

使用如下代码进行数据的创建:

    //读取数据模型文件
    nsurl *modelurl = [[nsbundle mainbundle]urlforresource:@"model" withextension:@"momd"];
    //创建数据模型
    nsmanagedobjectmodel * mom = [[nsmanagedobjectmodel alloc]initwithcontentsofurl:modelurl];
    //创建持久化存储协调者
    nspersistentstorecoordinator * psc = [[nspersistentstorecoordinator alloc]initwithmanagedobjectmodel:mom];
    //数据库保存路径
    nsurl * path =[nsurl fileurlwithpath:[[nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)lastobject] stringbyappendingpathcomponent:@"coredataexample.sqlite"]];
    //为持久化协调者添加一个数据接收栈
    /*
    可以支持的类型如下:
     nsstring * const nssqlitestoretype;//sqlite
     nsstring * const nsxmlstoretype;//xml
     nsstring * const nsbinarystoretype;//二进制
     nsstring * const nsinmemorystoretype;//内存
    */
    [psc addpersistentstorewithtype:nssqlitestoretype configuration:nil url:path options:nil error:nil];
    //创建数据管理上下文
    nsmanagedobjectcontext * moc = [[nsmanagedobjectcontext alloc]initwithconcurrencytype:nsmainqueueconcurrencytype];
    //关联持久化协调者
    [moc setpersistentstorecoordinator:psc];
    //创建数据对象
    /*
    数据对象的创建是通过实体名获取到的
    */
    schoolclass * models = [nsentitydescription insertnewobjectforentityforname:@"schoolclass" inmanagedobjectcontext:moc];
    //对数据进行设置
    models.name = @"第一班";
    models.stunum = @60;
    //进行存储
    if ([moc save:nil]) {
        nslog(@"新增成功");
    }
    nslog(@"%@",[[nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)lastobject] stringbyappendingpathcomponent:@"coredataexample.sqlite"]);

找到在打印出的路径,会发现里面多了一个sqlite文件,其中有一张表中添加进了一条数据。

二、查询数据

coredata中通过查询请求来对数据进行查询操作,查询请求由nsfetchrequest来进行管理和维护。

nsfetchrequest主要提供两个方面的查询服务:

1.提供范围查询的相关功能

2.提供查询结果返回类型与排序的相关功能

nsfetchrequest中常用方法如下:

//创建一个实体的查询请求 可以理解为在某个表中进行查询
+ (instancetype)fetchrequestwithentityname:(nsstring*)entityname;
//查询条件
@property (nullable, nonatomic, strong) nspredicate *predicate;
//数据排序
@property (nullable, nonatomic, strong) nsarray<nssortdescriptor *> *sortdescriptors;
//每次查询返回的数据条数
@property (nonatomic) nsuinteger fetchlimit;
//设置查询到数据的返回类型
/*
typedef ns_options(nsuinteger, nsfetchrequestresulttype) {
    nsmanagedobjectresulttype  = 0x00,
    nsmanagedobjectidresulttype  = 0x01,
    nsdictionaryresulttype          ns_enum_available(10_6,3_0) = 0x02,
    nscountresulttype    ns_enum_available(10_6,3_0) = 0x04
};
*/
@property (nonatomic) nsfetchrequestresulttype resulttype;
//设置查询结果是否包含子实体
@property (nonatomic) bool includessubentities;
//设置要查询的属性值
@property (nullable, nonatomic, copy) nsarray *propertiestofetch;
在schoolclass实体中查询数据,使用如下的代码:

    //创建一条查询请求
    nsfetchrequest * request = [nsfetchrequest fetchrequestwithentityname:@"schoolclass"];
    //设置条件为 stunum=60的数据
    [request setpredicate:[nspredicate predicatewithformat:@"stunum == 60"]];
    //进行查询操作
    nsarray * res = [moc executefetchrequest:request error:nil];
    nslog(@"%@",[res.firstobject stunum]);

进行数据初始化

    nsfetchedresultscontroller的初始化需要一个查询请求和一个数据操作上下文。代码示例如下:

//遵守协议
@interface viewcontroller ()<nsfetchedresultscontrollerdelegate>
{
    //数据桥接对象
    nsfetchedresultscontroller * _feccon;
}
@end

@implementation viewcontroller

- (void)viewdidload {
    [super viewdidload];
    //进行初始化操作
    nsurl *modelurl = [[nsbundle mainbundle]urlforresource:@"model" withextension:@"momd"];
    nsmanagedobjectmodel * mom = [[nsmanagedobjectmodel alloc]initwithcontentsofurl:modelurl];
    nspersistentstorecoordinator * psc = [[nspersistentstorecoordinator alloc]initwithmanagedobjectmodel:mom];
    nsurl * path =[nsurl fileurlwithpath:[[nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)lastobject] stringbyappendingpathcomponent:@"coredataexample.sqlite"]];
    [psc addpersistentstorewithtype:nssqlitestoretype configuration:nil url:path options:nil error:nil];
    nsmanagedobjectcontext * moc = [[nsmanagedobjectcontext alloc]initwithconcurrencytype:nsmainqueueconcurrencytype];
    [moc setpersistentstorecoordinator:psc];
    nsfetchrequest * request = [nsfetchrequest fetchrequestwithentityname:@"schoolclass"];
    //设置数据排序
    [request setsortdescriptors:@[[nssortdescriptor sortdescriptorwithkey:@"stunum" ascending:yes]]];
    //进行数据桥接对象的初始化
    _feccon = [[nsfetchedresultscontroller alloc]initwithfetchrequest:request managedobjectcontext:moc sectionnamekeypath:nil cachename:nil];
    //设置代理
    _feccon.delegate=self;
    //进行数据查询
    [_feccon performfetch:nil];
}
@end

用于初始化nsfecthedresultscontroller的数据请求对象必须设置一个排序规则。在initwithfetchrequest:managedobjectcontext:sectionnamekeypath:cachename:方法中,如果设置第三个参数,则会以第三个参数为键值进行数据的分区。当数据发生变化时,将通过代理进行方法的回调。

三、与uitableview进行数据绑定

-(uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath{
    uitableviewcell * cell = [tableview dequeuereusablecellwithidentifier:@"cellid"];
    if (!cell) {
        cell = [[uitableviewcell alloc]initwithstyle:uitableviewcellstylesubtitle reuseidentifier:@"cellid"];
    }
    //获取相应数据模型
    schoolclass * obj = [_feccon objectatindexpath:indexpath];
    cell.textlabel.text = obj.name;
    cell.detailtextlabel.text = [nsstring stringwithformat:@"有%@人",obj.stunum];
    return cell;
}
-(nsinteger)numberofsectionsintableview:(uitableview *)tableview{
    return [_feccon sections].count;
}
-(nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section{
    id<nsfetchedresultssectioninfo> info =  [_feccon sections][section];
    return [info numberofobjects];
   
}

效果如下:

iOS App中数据管理框架Core Data的基本数据操作教程

四、将数据变化映射到视图

//数据将要改变时调用的方法
- (void)controllerwillchangecontent:(nsfetchedresultscontroller *)controller
{
    //开启tableview更新预处理
    [[self tableview] beginupdates];
}
//分区数据改变时调用的方法
- (void)controller:(nsfetchedresultscontroller *)controller didchangesection:(id <nsfetchedresultssectioninfo>)sectioninfo atindex:(nsuinteger)sectionindex forchangetype:(nsfetchedresultschangetype)type
{
    //判断行为类型
    switch(type) {
        //插入新分区
        case nsfetchedresultschangeinsert:
            [[self tableview] insertsections:[nsindexset indexsetwithindex:sectionindex] withrowanimation:uitableviewrowanimationfade];
            break;
        //删除分区
        case nsfetchedresultschangedelete:
            [[self tableview] deletesections:[nsindexset indexsetwithindex:sectionindex] withrowanimation:uitableviewrowanimationfade];
            break;
        //移动分区
        case nsfetchedresultschangemove:
        //更新分区
        case nsfetchedresultschangeupdate:
            break;
    }
}
//数据改变时回调的代理
- (void)controller:(nsfetchedresultscontroller *)controller didchangeobject:(id)anobject atindexpath:(nsindexpath *)indexpath forchangetype:(nsfetchedresultschangetype)type newindexpath:(nsindexpath *)newindexpath
{
    switch(type) {
        //插入数据
        case nsfetchedresultschangeinsert:
            [[self tableview] insertrowsatindexpaths:@[newindexpath] withrowanimation:uitableviewrowanimationfade];
            break;
        //删除数据
        case nsfetchedresultschangedelete:
            [[self tableview] deleterowsatindexpaths:@[indexpath] withrowanimation:uitableviewrowanimationfade];
            break;
        //更新数据
        case nsfetchedresultschangeupdate:
            [self reloaddata];
            break;
        //移动数据
        case nsfetchedresultschangemove:
            [[self tableview] deleterowsatindexpaths:@[indexpath] withrowanimation:uitableviewrowanimationfade];
            [[self tableview] insertrowsatindexpaths:@[newindexpath] withrowanimation:uitableviewrowanimationfade];
            break;
    }
}
//数据更新结束调用的代理
- (void)controllerdidchangecontent:(nsfetchedresultscontroller *)controller
{
    [[self tableview] endupdates];
}