CoreData 学习之路

来源:互联网 发布:英文搜题软件 编辑:程序博客网 时间:2024/06/15 08:32

Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间,我们不需要编写任何SQL语句,这个有点类似于著名的Hibernate持久化框架,不过功能肯定是没有Hibernate强大的。简单地用下图描述下它的作用:

abc

左边是关系模型,即数据库,数据库里面有张person表,person表里面有id、name、age三个字段,而且有2条记录;

右边是对象模型,可以看到,有2个OC对象;

利用Core Data框架,我们就可以轻松地将数据库里面的2条记录转换成2个OC对象,也可以轻松地将2个OC对象保存到数据库中,变成2条表记录,而且不用写一条SQL语句。


模型文件

  在Core Data,需要进行映射的对象称为实体(entity),而且需要使用Core Data的模型文件来描述app中的所有实体和实体属性。这里以Person(人)和Card(身份证)2个实体为例子,先看看实体属性和实体之间的关联关系:
abc
Person实体中有:name(姓名)、age(年龄)、card(身份证)三个属性
Card实体中有:no(号码)、person(人)两个属性
接下来看看创建模型文件的过程:
1.选择模板
abcabc

2.添加实体



3.添加Person的2个基本属性


4.添加Card的1个基本属性



5.建立Card和Person的关联关系

        

右图中的表示Card中有个Person类型的person属性,目的就是建立Card跟Person之间的一对一关联关系(建议补上这一项),在Person中加上Inverse属性后,你会发现Card中Inverse属性也自动补上了



了解NSManagedObject

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

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

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

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


CoreData中的核心对象



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


代码实现

导入#import<CoreData/CoreData.h>

贴代码之前需要了解6个对象:

1、NSManagedObjectContext

管理对象,上下文,持久性存储模型对象

2、NSManagedObjectModel

被管理的数据模型,数据结构

3、NSPersistentStoreCoordinator

连接数据库的

4、NSManagedObject

被管理的数据记录

5、NSFetchRequest

数据请求

6、NSEntityDescription

表格实体结构

此外还需要知道.xcdatamodel文件编译后为.momd或者.mom文件



1.搭建上下文环境
#pragma mark - CoreData Stack- (NSManagedObjectContext *)managedObjectContext{    if (_managedObjectContext) {        return _managedObjectContext;    }    NSPersistentStoreCoordinator * coordinator = [self persistentStoreCoordinator];    if (coordinator) {        _managedObjectContext = [[NSManagedObjectContext alloc] init];        // 初始化上下文,设置persistentStoreCoordinator属性        [_managedObjectContext setPersistentStoreCoordinator:coordinator];    }    return _managedObjectContext;}-(NSPersistentStoreCoordinator *)persistentStoreCoordinator{    if (_persistentStoreCoordinator) {        return _persistentStoreCoordinator;    }    // 构建SQLite数据库文件的路径    NSURL * storeUrl = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"NewsModel.sqlite"];    NSError * error = nil;    // 传入模型对象,初始化NSPersistentStoreCoordinator    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:[self managedObjectModel]];    // 添加持久化存储库,这里使用SQLite作为存储库    if ([_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {        return nil;    }    return _persistentStoreCoordinator;}//从应用程序包中加载模型文件。.xcdatamodel(模型文件)文件编译后为.momd或者.mom文件-(NSManagedObjectModel *)managedObjectModel{    if (_managedObjectModel) {        return _managedObjectModel;    }    NSURL * modelUrl = [[NSBundle mainBundle]URLForResource:@"NewsModel" withExtension:@"momd"];    _managedObjectModel = [[NSManagedObjectModel alloc]initWithContentsOfURL:modelUrl];    return _managedObjectModel;}- (NSURL *)applicationDocumentsDirectory{    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}

2.增删改查操作。
//插入数据- (void)insertCoreData:(NSMutableArray *)dataArray{    NSManagedObjectContext * context = [self managedObjectContext];    for (News * info in dataArray) {        //此处添加到的表为News这个实体        News * newsInfo = [NSEntityDescription insertNewObjectForEntityForName:NewsTableName inManagedObjectContext:context];        newsInfo.newsid = info.newsid;        newsInfo.title = info.title;        newsInfo.imgurl = info.imgurl;        newsInfo.descr = info.descr;        newsInfo.islook = info.islook;                NSError *error;        if (![context save:&error]) {            NSLog(@"%@",error.localizedDescription);        }    }}//查询.- (NSMutableArray *)selectData:(int)pageSize andOffset:(int)currentPage{    NSManagedObjectContext * context = [self managedObjectContext];        //限定查询结果的数量    //selFetchLimit    //查询的偏移量    //setFetchOffset            NSFetchRequest * fetchRequest = [[NSFetchRequest alloc]init];    [fetchRequest setFetchLimit:pageSize];    [fetchRequest setFetchOffset:currentPage];    //此处添加到的表为News这个实体    NSEntityDescription * entity = [NSEntityDescription entityForName:NewsTableName inManagedObjectContext:context];    [fetchRequest setEntity:entity];    NSError * error;    NSArray * fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];    NSMutableArray * resultArray = [NSMutableArray array];        for (News * info in fetchedObjects) {        [resultArray addObject:info];    }    return resultArray;}//删除操作- (void)deleteData{    NSManagedObjectContext * context = [self managedObjectContext];    //此处添加到的表为News这个实体    NSEntityDescription * entity = [NSEntityDescription entityForName:NewsTableName inManagedObjectContext:context];    NSFetchRequest * fetchRequest = [[NSFetchRequest alloc]init];    [fetchRequest setIncludesPropertyValues:NO];    [fetchRequest setEntity:entity];    NSError * error;    NSArray * datas = [context executeFetchRequest:fetchRequest error:&error];    if (!error && datas && [datas count]) {        for (NSManagedObject * obj in datas) {            [context deleteObject:obj];        }    }    if (![context save:&error]) {        NSLog(@"%@",error.localizedDescription);    }}//更新- (void)updateData:(NSString *)newsId withIsLook:(NSString *)isLook{    NSManagedObjectContext * context = [self managedObjectContext];    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"newsid like[cd] %@",newsId];    //https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pCreating.html    //首先还是需要建立一个request    NSFetchRequest * request = [[NSFetchRequest alloc]init];    [request setEntity:[NSEntityDescription entityForName:newsId inManagedObjectContext:context]];    [request setPredicate:predicate];        NSError * error = nil;    NSArray * result = [context executeFetchRequest:request error:&error];    for (News * info in result) {        info.islook = isLook;    }        //保存    if (![context save:&error]) {        NSLog(@"%@",error.localizedDescription);    }}
在上面对CoreData 的使用中,基本都是在主线程中对数据库进行的操作,在主 managed object context 中处理导入数据并不是最优的,主线程可能被堵塞,UI 可能没有反应。大多数时候,在主线程中处理的工作应该是最小限度的,并且造成的延迟应当难以察觉。如果你的情况正是这样,那非常好。然而,如果我们想要做些额外的努力,我们可以在后台线程中处理导入操作。
Apple 在 WWDC 会议以及官方的《Core Data 编程指南》文档的「Concurrency with Core Data」 一节中,对于并发的 Core Data,推荐给开发者两种选择。这两种都需要独立的 managed object contexts,它们要么共享同样的 persistent store coordinator,要么不共享。在处理很多改变时,拥有独立的 persistent store coordinators 提供更出色的性能,因为仅需要的锁只是在 sqlite 级别。拥有共享的 persistent store coordinator 也就意味着拥有共享缓存,当你没有做出很多改变时,这会很快。所以,根据你的情况而定,你需要衡量哪种方案更好,然后选择是否需要一个共享的 persistent store coordinator。当主 context 是只读的情况下,根本不需要锁,因为 iOS 7 中的 sqlite 有写前记录功能并且支持多重读取和单一写入。然而,对于我们的示范目的,我们会使用完全独立堆栈的处理方式。我们使用下面的代码设置一个 managed object contex

- (id)initWithStoreURL:(NSURL*)storeURL modelURL:(NSURL*)modelURL{    self = [super init];    if (self) {        self.storeURL = storeURL;        self.modelURL = modelURL;        [self setupManagedObjectContexts];    }    return self;}- (void)setupManagedObjectContexts{    self.managedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSMainQueueConcurrencyType];    self.managedObjectContext.undoManager = [[NSUndoManager alloc] init];    self.backgroundManagedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSPrivateQueueConcurrencyType];    self.backgroundManagedObjectContext.undoManager = nil;    [[NSNotificationCenter defaultCenter]            addObserverForName:NSManagedObjectContextDidSaveNotification                        object:nil                         queue:nil                    usingBlock:^(NSNotification* note) {        NSManagedObjectContext *moc = self.managedObjectContext;        if (note.object != moc) {            [moc performBlock:^(){                [moc mergeChangesFromContextDidSaveNotification:note];            }];        }     }];}- (NSManagedObjectContext *)setupManagedObjectContextWithConcurrencyType:(NSManagedObjectContextConcurrencyType)concurrencyType{    NSManagedObjectContext *managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:concurrencyType];    managedObjectContext.persistentStoreCoordinator =            [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];    NSError* error;    [managedObjectContext.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType                                                                  configuration:nil                                                                            URL:self.storeURL                                                                        options:nil                                                                          error:&error];    if (error) {        NSLog(@"error: %@", error.localizedDescription);        NSLog(@"rm \"%@\"", self.storeURL.path);    }    return managedObjectContext;}- (NSManagedObjectModel*)managedObjectModel{    return [[NSManagedObjectModel alloc] initWithContentsOfURL:self.modelURL];}
然后我们调用这个方法两次,一次是为主 managed object context,一次是为后台 managed object context:
self.managedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSMainQueueConcurrencyType];    self.managedObjectContext.undoManager = [[NSUndoManager alloc] init];    self.backgroundManagedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSPrivateQueueConcurrencyType];    self.backgroundManagedObjectContext.undoManager = nil;
注意传递的参数 NSPrivateQueueConcurrencyType 告诉 Core Data 创建一个独立队列,这将确保后台 managed object context 的运行发生在一个独立的线程中。
现在就剩一步了:每当后台 context 保存后,我们需要更新主线程。我们在之前第 2 期的这篇文章中描述了如何操作。我们注册一下,当 context 保存时得到一个通知,如果是后台 context,调用 mergeChangesFromContextDidSaveNotification: 方法。这就是我们要做的所有事情:
[[NSNotificationCenter defaultCenter]            addObserverForName:NSManagedObjectContextDidSaveNotification                        object:nil                         queue:nil                    usingBlock:^(NSNotification* note) {        NSManagedObjectContext *moc = self.managedObjectContext;        if (note.object != moc) {            [moc performBlock:^(){                [moc mergeChangesFromContextDidSaveNotification:note];            }];        }     }];




本文出自于csdn上的博客,感谢他们的付出,节约了很多时间!

IOS之分析网易新闻存储数据(CoreData的使用,增删改查)
Core Data入门
后台线程处理数据CoreData


0 0
原创粉丝点击