CoreData数据库

了解CoreData

CoreData是一个数据库,是对SQLite的封装。Xcode内部集成,coredata是orm。ORM(Object Relational Mapping)对象关系映射,orm操作数据库的原理:自己不写SQL语句通过APP里的对象和数据库的表映射。 Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,这个有点类似于著名的Hibernate持久化框架,不过功能肯定是没有Hibernate强大的。

 

CoreData.framework : iOS中提供了对原始SQLite数据库API访问的封装,通过这个framework来管理数据缓存和持久数据要比使用SQL语句操作SQLite数据库简单和方便许多。

 

面试题:sqlite与coreData的简单比较:

首先,coredata和sqlite的概念不同,core为对象周期管理,而sqlite为dbms。
下面的讨论以使用core data来做数据持久化并使用sqlite做backend存储的情况为前提。

    1. 使用方便性。实际上,一个成熟的工程中一定是对数据持久化进行了封装的,因此底层使用的到底是core data还是sqlite,不应该被业务逻辑开发者关心。因此,即使习惯写SQL查询的人,也应该避免在业务逻辑中直接编写SQL语句。
    2. 存 储性能,在写入性能上,因为都是使用的sqlite格式作为磁盘存储格式,因此其性能是一样的,如果你觉得用core data写的慢,很可能是你用sqlite的时候写的每条数据的内容没有core data时多,或者是你批量写入的时候每写入一条就调用了一次save。
    3. 查 询性能,core data因为要兼容多种后端格式,因此查询时,其可用的语句比直接使用sqlite少,因此有些fetch实际上不是在sqlite中执行的。但这样未必 会降低查询效率。因为iPhone的flash memory速度还是很快的。我的经验是大部分时候,在内存不是很紧张时,直接fetch一个entity的所有数据然后在内存中做filter往往比使 用predicate在fetch时过滤更快。如果你觉的查询慢,很可能是查询方式有问题,可以把core data的debug模式打开,看一下到底执行了多少SQL语句,相信其中大部分是可以通过改写core data的调用方式避免的。
    4. core data的一个比较大的痛点是多人合作开发的时候,管理coredata的模型需要很小心,尤其是合并的时候,他的data model是XML格式的,手动resolve比较烦心。
    5. core data还有其他sql所不具备的优点,比如对undo的支持,多个context实现sketchbook类似的功能。为ManagedObject优化的row cash等。
    6. 另外core data是支持多线程的,但需要thread confinement的方式实现,使用了多线程之后可以最大化的防止阻塞主线程。

了解NSManagedObject

通过Core Data从数据库取出的对象,默认情况下都是NSManagedObject对象

2.NSManagedObject的工作模式有点类似于NSDictionary对象,通过键-值对来存取所有的实体属性

1> setValue:forKey:存储属性值(属性名为key)

2> valueForKey:获取属性值(属性名为key)

 

CoreData中的核心对象

注:黑色表示类名,红色表示类里面的一个属性
发步骤总结:
1.初始化NSManagedObjectModel对象,加载模型文件,读取app中的所有实体信息
2.初始化NSPersistentStoreCoordinator对象,添加持久化库(这里采取SQLite数据库)
3.初始化NSManagedObjectContext对象,拿到这个上下文对象操作实体,进行CRUD操作

代码实现

添加实体:ContactList.xdatamodeld

 

在RootViewController.m文件里:(前面声明及准备工作)

 1 #import "RootViewController.h"
 2 #import "ContactList.h"
 3 #import <CoreData/CoreData.h>
 4 
 5 @interface RootViewController ()<UITableViewDataSource,UITableViewDelegate>
 6 {
 7     
 8     NSMutableArray *dataAry;
 9     UITableView *tv;
10     UITextField *txtName;
11     UITextField *txtPhoneNum;
12     
13     NSInteger currentRow; //当前操作的行
14     
15     NSManagedObjectContext *moc;     //coredata操作数据库的核心对象
16 }
17 @end
18 
19 @implementation RootViewController
20 
21 - (void)viewDidLoad {
22     [super viewDidLoad];
23     // Do any additional setup after loading the view.
24     [self createUI];
25     [self createData];
26 }

搭建上下文环境,创造数据源,实现createData

 1 -(void)createData{
 2     dataAry=[NSMutableArray array];
 3     //读取库的映射文件,先找路径。【注意】库的映射文件的扩展名是momd
 4     NSString *path=[[NSBundle mainBundle]pathForResource:@"PhoneData" ofType:@"momd"];
 5     NSManagedObjectModel *model=[[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]];
 6     //建立管理数据模型的对象
 7     NSPersistentStoreCoordinator *psc=[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
 8     //创建数据库的资源路径
 9     NSString *dbPath=[NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/coredb.sqlite"];
10     NSLog(@"路径:%@",dbPath);
11     NSError *error=nil;
12     //创建数据库状态的类
13     //此类没有时间意义。作用:判断。 添加持久化存储库,这里使用SQLite作为存储库 
14     NSPersistentStore  *store=[psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dbPath] options:nil error:&error];
15     if (!store) {
16         NSLog(@"创建失败,错误信息:%@",error);
17     }
18     
19     //以上代码执行后,如果执行成功,数据库及表就已经创建成功
20     
21     //创建管理对象,管理整个数据库
22     moc=[[NSManagedObjectContext alloc] init];
23     //设置管理对象管理哪个数据库
24     moc.persistentStoreCoordinator=psc;
25     //做映射。类和数据库里的哪个表对应
26     NSFetchRequest *fr=[NSFetchRequest fetchRequestWithEntityName:@"ContactList"];
27     //执行的是查询操作
28     NSArray *arr=[moc executeFetchRequest:fr error:nil];
29     dataAry.array=arr;
30     [tv reloadData];
31 }

创建UI,实现createUI:

 1 -(void)createUI{
 2     txtName=[[UITextField alloc] initWithFrame:CGRectMake(10, 25, 100, 20)];
 3     txtName.borderStyle=UITextBorderStyleRoundedRect;
 4     txtName.backgroundColor=[UIColor orangeColor];
 5     [self.view addSubview:txtName];
 6     txtPhoneNum=[[UITextField alloc ] initWithFrame:CGRectMake(115, 25, 100, 20)];
 7     txtPhoneNum.borderStyle=UITextBorderStyleRoundedRect;
 8     txtPhoneNum.backgroundColor=[UIColor orangeColor];
 9     [self.view addSubview:txtPhoneNum];
10     
11     NSArray *titleAry=@[@"",@"",@"",@""];
12     for (int i=0; i<titleAry.count; i++) {
13         UIButton *btn=[[UIButton alloc] initWithFrame:CGRectMake(220+i*35, 25, 30, 20)];
14         btn.backgroundColor=[UIColor grayColor];
15         [btn setTitle:titleAry[i] forState:UIControlStateNormal];
16         btn.tag=i+1;
17         [btn addTarget:self action:@selector(btn_Click:) forControlEvents:UIControlEventTouchUpInside];
18         [self.view addSubview:btn];
19     }
20     tv=[[UITableView alloc ] initWithFrame:CGRectMake(0, 50, 375, 600) style:UITableViewStylePlain];
21     tv.delegate=self;
22     tv.dataSource=self;
23     [self.view addSubview:tv];
24 }
25 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
26     return dataAry.count;
27 }
28 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
29     NSString *identifier=@"coredata";
30     UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier];
31     if (!cell) {
32         cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
33     }
34     if (dataAry.count>0) {
35         ContactList *contactL=dataAry[indexPath.row];
36         if (contactL) {
37             cell.textLabel.text=contactL.name;
38             cell.detailTextLabel.text=contactL.phoneNum;
39         }
40     }
41     return cell;
42 }

通过按钮的增删改查实现数据库的基本操作(重点):

-(void)btn_Click:(UIButton *)sender{
    NSError *error=nil;
    //完成具体的增删改查
    switch ((int)sender.tag) {
        case 1:
            //增加
        {
            ContactList *contact=[NSEntityDescription insertNewObjectForEntityForName:@"ContactList" inManagedObjectContext:moc];
            contact.name=txtName.text;
            contact.phoneNum=txtPhoneNum.text;
           // 只要在更改了实体对象的属性后调用[moc save:&error],就能将更改的数据同步到数据库
            if ([moc save:&error]) {
                //如果保存成功,从数据库中获取表里的所有数据
                [dataAry addObject:contact];
                [tv reloadData];
            }
            else{
                NSLog(@"Reason:%@",error);
            }
        }
            break;
        case 2:
            //删除
        {
            if (dataAry.count==0) {
                NSLog(@"没有要删除的数据");
                return;
            }
            ContactList *contact=dataAry[currentRow];
            [moc deleteObject:(NSManagedObject *)contact];
            if ([moc save:&error]) {
                [dataAry removeObject:contact];
                [tv reloadData];
            }else{
                NSLog(@"%@",error);
            }
        }
            break;
        case 3:
            //修改
        {
            //先获取要修改的对象
            ContactList *contact=dataAry[currentRow];
            contact.name=txtName.text;
            contact.phoneNum=txtPhoneNum.text;
            if ([moc save:&error]) {
                [tv reloadData];
            }else{
                NSLog(@"%@",error);
            }
        }
            break;
        default:
            //查询
        {
            //设置排序(按照phoneNum降序)
            NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"phoneNum" ascending:NO];
//初始化一个请求,并设置请求的实体 NSFetchRequest
*fr=[NSFetchRequest fetchRequestWithEntityName:@"ContactList"]; fr.sortDescriptors = [NSArray arrayWithObject:sort]; NSPredicate *p=[NSPredicate predicateWithFormat:@"name like %@ and phoneNum like %@",[NSString stringWithFormat:@"*%@*",txtName.text],[NSString stringWithFormat:@"%@*",txtPhoneNum.text]]; //声明查询对象 fr.predicate=p; NSArray *ary=[moc executeFetchRequest:fr error:nil]; dataAry.array=ary; [tv reloadData]; // 设置条件过滤(搜索注意:设置条件过滤时,数据库SQL语句中的%要用*来代替,所以180%应该写成180*) } break; } } -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ currentRow=indexPath.row; ContactList *contact=dataAry[currentRow]; txtName.text=contact.name; txtPhoneNum.text=contact.phoneNum; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. }

实现效果:

 

转载于:https://www.cnblogs.com/crushing/p/4820214.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值