使用 NSPersistentnspathstore2Coordinator 的意义吗

作者/Matt Drance
前苹果公司布道师。在苹果公司工作了8年,然后创立了一家iOS开发与咨询公司Bookhouse Software。他还为Pragmatic Studio培训iOS开发者,在Apple Outsider()上分享对行业的见解。除了编码、写作、教学以及履行超级奶爸的义务之外,Matt还喜欢在北加州滑雪和赛车。
我们启动的每个项目,最终都免不了从以前的项目或苹果公司的示例代码模板中复制与粘贴事务性的核心数据(Core Data)代码。对于每个新项目,我们需要可靠而切实可行的着手点。
核心数据在减少数据库操作所需的代码方面,效果非常出色。然而,在每个使用核心数据的项目中,仍然还有很多冗余的工作。我们需要设置持久存储、模型和托管对象上下文(managed object context),确保支持模型版本间的迁移。如果放置的地方不对,这些代码可能会在项目中产生讨厌的混乱和依赖关系。
本攻略介绍一种基本的数据模型。几乎每个基于核心数据的app,都需要标准的初始化工作,这将由这种数据模型来完成。我们可以方便地修改或子类化这个模型类,使它满足我们app的需要。
基本数据模型的首要任务,是把每个基于核心数据的应用程序都需要执行的底层初始化操作抽象出来。它初始化托管对象模型、加载持久存储协调器(persistent storage coordinator),并生成默认的托管对象上下文。这个类默认使用SQLite存储。
只读的managedObjectModel属性是懒初始化的,它指向一个模型文件,默认的文件名为应用程序包标识符的最后一个部分,扩展名为.momd。比如,如果包标识符为com.pragprog.BasicDataModel,模型的文件名就是BasicDataModel.momd。我们可以通过修改-modelName和-pathToModel来设置模型文件的名字和路径。
BasicDataModel/Shared/PRPBasicDataModel.m
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel == nil) {
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToModel]];
managedObjectModel = [[NSManagedObjectModel alloc]
initWithContentsOfURL:storeURL];
return managedObjectM
BasicDataModel/Shared/PRPBasicDataModel.m
- (NSString *)modelName {
[[[NSBundle mainBundle] bundleIdentifier] pathExtension];
- (NSString *)pathToModel {
NSString *filename = [self modelName];
NSString *localModelPath = [[NSBundle mainBundle] pathForResource:filenameofType:@&momd&];
NSAssert1(localModelPath, @&Could not find '%@.momd'&, filename);
return localModelP
使用有版本控制的模型
如果使用核心数据,从一开始就使用有版本的模型是有好处的。要是开始时用的是显式的.mom文件,后来改为有版本的.momd文件夹,可能会导致项目中出现陈旧或相互冲突的数据。开发过程中,这会带来难以定位的错误,在使用mergedModelFromBundles:来生成模型的时候更是如此。如果是在产品从1.0升级到2.0时做的改动,这些让人头疼的问题可能跑到用户那里去。所以要从一开始就使用.momd文件。
本攻略使用更明确的-[NSManagedObjectModel initWithContentsOfURL:],因为在包中可能会加入最初没有想到的数据模型。随Xcode 4一起发布的模板就是以这种方式创建的,但较早的项目有可能不是。请检查自己的项目,确保已经做好了版本迁移的准备。
只读的persistentStoreCoordinator属性是懒初始化的,预设为在模型版本间执行自动轻量迁移。这样,如果添加的模型新版本只是做了小的改动,并支持轻量迁移,我们就不需要做额外的工作。
请记住,迁移并不总是轻而易举的。对核心数据模型的基本改动,比如添加属性或修改属性名称,通常可以自动迁移。但是,很多情况下,模型的改动太复杂,因而无法自动迁移。在对已经发布的数据模型进行改动之前,请先阅读苹果公司iOS Dev Center里的“核心数据模型版本控制与数据迁移编程指南”(Core Data Model Versioning and Data Migration Programming Guide)。另外,一定要先在Xcode里添加模型版本,然后再作修改。千万不要修改没作管理的模型版本!
BasicDataModel/Shared/PRPBasicDataModel.m
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]];
NSPersistentStoreCoordinator *
psc = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:self.managedObjectModel];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES],
NSInferMappingModelAutomaticallyOption,
NSError *error =
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:error
forKey:NSUnderlyingErrorKey];
NSException *exc =
NSString *reason = @&Could not create persistent store.&;
exc = [NSException onWithName:NSInternalInconsistencyException
reason:reason
userInfo:userInfo];
persistentStoreCoordinator =
这段代码还有一个功能,它支持在数据库不存在时,对跟app一起发布的数据库进行“预安装”。我们在创建模型的持久存储之前进行这一处理,所以在程序第一次启动时可以向用户提供一些占位数据。这部分不是必需的,也不必禁掉这段代码。如果不需要占位数据,就不必提供预安装的数据库文件。
BasicDataModel/Shared/PRPBasicDataModel.m
NSString *pathToLocalStore = [self pathToLocalStore];
NSString *pathToDefaultStore = [self pathToDefaultStore];
NSError *error =
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL noLocalDBExists = ![fileManager fileExistsAtPath:pathToLocalStore];
BOOL defaultDBExists = [fileManager fileExistsAtPath:pathToDefaultStore];
if (noLocalDBExists && defaultDBExists) {
if (![[NSFileManager defaultManager] copyItemAtPath:pathToDefaultStore
toPath:pathToLocalStore
error:&error]) {
NSLog(@&Error copying default DB to %@ (%@)&,
pathToLocalStore, error);
NSError的使用
按照苹果公司的NSPersistentStore的参考文档和通常的Cocoa惯例,除非API返回了表示出错的值(通常是nil或NO),否则不应直接查看传给API的NSError参数。如果没有遵守这个指南,就可能导致难以捉摸而严重的程序bug。
数据模型背后的各个文件(模型文件、工作数据库和预安装的“默认”数据库)的位置,被抽象到存取器方法中,我们可以对它们进行修改或覆盖,以定制这些路径。
-storeFileName返回SQLite数据库的名字,它与模型(.momd)文件的命名方式类似:如果模型叫BasicDataModel.momd,那么存储文件就叫BasicDataModel.sqlite。
pathToLocalStore 返回应用程序沙盒(app sandbox)中活动数据库的路径。默认为~/Documents/&storeFileName&。
-pathToDefaultStore返回应用程序包中默认数据库的路径,用于预安装。
BasicDataModel/Shared/PRPBasicDataModel.m
- (NSString *)storeFileName {
return [[self modelName] stringByAppendingPathExtension:@&sqlite&];
-(NSString *)pathToLocalStore {
NSString *storeName = [self storeFileName];
NSString *docPath = [self documentsDirectory];
return [docPath stringByAppendingPathComponent:storeName];
-(NSString *)pathToDefaultStore {
NSString *storeName = [self storeFileName];
return [[NSBundle mainBundle] pathForResource:storeName ofType:nil];
NSManagedObjectContext类是大多数核心数据操作的主要接口。我们基本的数据模型以懒加载的方式创建单一“主”上下文,用于其全部查询。因为这是个“基本”模型,所以没有下功夫去做多上下文或多线程的支持。如果需要使用多个上下文,可以简单地修改这个类,生成新的上下文,或者使用主上下文的持久存储协调器来动态创建。
BasicDataModel/Shared/PRPBasicDataModel.m
- (NSManagedObjectContext *)mainContext {
if (mainContext == nil) {
mainContext = [[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *psc = self.persistentStoreC
[mainContext setPersistentStoreCoordinator:psc];
return mainC
本攻略附带的BasicDataModel项目使用Interface Builder创建模型,并把它连接到应用程序委托,如图38所示。根据需要,可以把模型或者来自模型的NSManagedObjectContext,传给其他需要访问模型数据的对象。请记住,使用一个上下文的持久存储协调器,可以创建新的托管对象上下文。所以,需要的话,我们可以不对模型做任何引用,而只是引用app委托。
我们可以在代码中或使用Interface Builder来实例化BasicDataModel。Interface Builder可以很方便地识别出模型,并把它连接到app委托的dataModel属性。
使用Interface Builder初始化模型
在应用程序中使用核心数据,意味着我们需要做一些多余的工作。把这些代码分离于一处以便于复用,可以减少每个项目的工作量,并避免粗心引起的bug。
你可能看到过其他app里很酷的特性和技巧,却苦于没有时间仔细弄清楚个中原理。针对iOS开发所常见的问题和模式提供了一系列简洁、实用的解决方案。书中收录了最新的iOS软件开发的最佳做法,涵盖了应用开发及构建优雅解决方案的必备知识,能让你的iPhone和iPad应用程序开发实力更上一个台阶。本文选自
本文目前还没有评论……2866人阅读
遇到一个很奇怪的现象。unit测试时,coreData部分报错:This NSPersistentStoreCoordinator has no persistent stores.
但实际跑程序时。增删保存都没问题。
我花了很多的时间在问题抛出的地方在[contextsave:&error];&
后来发现,早在初期化_persistentStoreCoordinator 时就报错了
& &&if (![_persistentStoreCoordinator
& & & & &addPersistentStoreWithType:NSSQLiteStoreType
& & & & &configuration:nil
URL:storeUrl
options:nil
error:&error]) {
& & & &// Handle the error.
&error 显示的信息为The model used to open the store is incompatible with the one used to create
上网搜了下,大意是说可能在改变entities的atrributes时损坏了存储文件。直接把存储文件删除即可。
我试了下,果然就ok了。
另外两个人和我的现象是一样的,不过在storeUrl指定的地方根本没有文件夹,别说文件了。按照storeUrl
的路径把文件夹建好,也就ok了。
我还有个疑问,为什么实际跑画面的时候是好的。只有单体测试的时候有问题?
我又在跑画面的时候,跟进去看了下。实际跑画面的storeUrl的根路径与单体时不同,有一串看似是UUID的随机数。
估计是跑画面的时候有建新目录的权限。
而跑单体的时候既没有建目录权限,也没有删文件权限。所以当存储改变时会报错。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:123126次
积分:2031
积分:2031
排名:第13518名
原创:81篇
转载:13篇
评论:21条
(1)(2)(1)(1)(3)(1)(1)(4)(5)(5)(7)(1)(1)(2)(1)(2)(1)(4)(1)(2)(1)(1)(1)(1)(1)(3)(2)(6)(1)(2)(1)(4)(2)(2)(8)(1)(1)(1)(1)(1)(1)(1)(2)(6)如何设置核心数据的轻量级迁移使用magicalrecord?
如何设置核心数据的轻量级迁移使用magicalrecord?
I have hit a brick wall trying to setup lightweight migration of Core Data using MagicalRecord.
I have looked at all of the posts on this subject, using Google and SO.
I understand how the persistentStoreCoordinator works and what the settings I am trying to make also do.
Here's my code:
AppDeligate.h
NSPersistentStoreCoordinator *persistentStoreC
AppDelegate.m
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreC
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"saori.sqlite"]];
// handle db upgrade
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *error =
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle error
return persistentStoreC
I'm getting the following errors, which I what I don't know is where are these objects (I have looked in my app, and found nothing):
No visible @interface for 'AppDelegate' declares the selector 'applicationDocumentsDirectory' and
No visible @interface for 'AppDelegate' declares the selector 'managedObjectModel'
I have already created the stores:
Most, if not all of the code I have
I don't know if MagicalRecord handles this for me or not because I can't find any docs that would indicate how to do this using MR.
My question is: what do I have to do to make this work?
日50分57秒
The whole point of MagicalRecord is that this is managed for you:
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:####];
Check the docs about the Core Data stack setup .
日50分57秒
As of my understanding of the question, i suggest you to use this
[MagicalRecord setupAutoMigratingCoreDataStack]
If you have not changed the model version, change it to new model created from the old model
日50分57秒
Make sure you check all of these things:
In your AppDelegate.m file:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[MagicalRecord setupAutoMigratingCoreDataStack];
If you haven't versioned your model already:
Select your data model
Editor -> Add Model Version
Name the new version, Finish
There should be two versions now. Select the file as shown.
Change the Model Version to your new version
The new version should be checked now
日50分57秒
& 2016 91R.NET 版权所有知识(14)
什么是CoreData
在现代应用开发中,关于做数据持久化处理中,越来越多的人使用CoreData.因为用苹果的话来说它可以节约30%—70%的代码量 .(对于这个说法,大家可以各抒起见,欢迎吐槽),当然,对比与其他几个数据持久化的操作(如:写入,归档,SQLite),个人认为还是有好多好处的,它对sqlite进行了分装,只能用在iphone上
下面我们来看一下它的概念
1.Core Data 是数据持久化存储的最佳方式
2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,
内存里或自定义数据类型
那么它有什么好处呢
1.能够合理管理内存,避免使用sql的麻烦,高效
2.支持可视化建模
3.支持数据库升级 (关键点) (例如数据库中添加字段)
下面我们来了解一下它的构成,当然在后面还会有详细的介绍
(1)NSManagedObjectContext(被管理的数据上下文)(数据管理:临时数据库)
操作实际内容(操作持久层)
作用:插入数据,查询数据,删除数据
(2)NSManagedObjectModel(被管理的数据模型,模具)
数据库所有表格或数据结构,包含各实体的定义信息
作用:添加实体的属性,建立属性之间的关系
操作方法:视图编辑器,或代码
(3)NSPersistentStoreCoordinator(持久化存储助理)(数据连接器)
相当于数据库的连接器
与数据库直接打交道
作用:设置数据存储的名字,位置,存储方式,和存储时机
(4)NSManagedObject(被管理的数据记录)
相当于数据库中的表格记录
(5)NSFetchRequest(获取数据的请求)
相当于查询语句
(6)NSEntityDescription(实体结构)
相当于表格结构
(7)后缀为.xcdatamodeld的包
里面是.xcdatamodel文件,用数据模型编辑器编辑
编译后为.momd或.mom文件
属性和方法简介
我们简单介绍了CoreData创建的基本界面操作,今天我们简单介绍一下关于勾选user coreData后在AppDalageta.h生成的一些属性和方法的意义和使用.
在建立工程时,点击 use core Data 时
系统会在AppDelegate.h 中生成一些系统自带的方法
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectC
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectM
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreC
在AppDelegate.m中的实现
- (NSURL *)applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel != nil) {
return _managedObjectM
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Lesson04CoreData" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectM
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) {
return _persistentStoreC
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Lesson04CoreData.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSMigratePersistentStoresAutomaticallyOption:@YES,NSInferMappingModelAutomaticallyOption :@YES} error:&error]) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureR
dict[NSUnderlyingErrorKey] =
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
return _persistentStoreC
- (NSManagedObjectContext *)managedObjectContext {
if (_managedObjectContext != nil) {
return _managedObjectC
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectC
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
关于数据库的增删改查的操作
在viewController.m中关联button的方法中实现
添加数据到数据库中
1.通过实体描述对象创建实体类
Student *student =[NSEntityDescription insertNewObjectForEntityForName:@”Student” inManagedObjectContext:self.managedObjectContext];
2.给实体类赋值
3.要想保存到真实的数据库中 必须调用被管理对象的上下文的Save方法
NSError *error =
[self.managedObjectContext
save:&error];
if (error) {
NSLog(@”保存失败”);
[self.dataArray addObject:student];
//让实体对象显示在cell上
NSIndexPath *indenPath = [NSIndexPath indexPathForRow:self.dataArray.count -1 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indenPath] withRowAnimation:UITableViewRowAnimationAutomatic];
在viewController.m 中的viewDidLoad中实现下面方法
self.dataArray = [[NSMutableArray alloc]init];
self.managedObjectContext = [(AppDelegate *)[UIApplication sharedApplication].delegate managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Student"];
NSPredicate
*predicate = [NSPredicate predicateWithFormat:@"teacher = %@",self.teacher];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
[request setSortDescriptors:@[sortDescriptor]];
NSArray *resultArray = [self.managedObjectContext executeFetchRequest:request error:nil];
if (resultArray & 0) {
[self.dataArray addObjectsFromArray:resultArray];
[self.tableView reloadData];
注意:在这里条件查询是可选的,通过谓语设置条件 多个条件使用and连接
今天就和大家介绍到这里,后面会给大家介绍关于CoreData的两个实体类建议福关系和属性,数据库升级的内容,谢谢大家
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:3239次
排名:千里之外
原创:33篇
转载:10篇
(1)(2)(5)(2)(3)(11)(19)详解持久化Core Data框架的原理以及使用---转自Bison的技术博客 - 简书
下载简书移动应用
写了37255字,被1405人关注,获得了1866个喜欢
详解持久化Core Data框架的原理以及使用---转自Bison的技术博客
1.原理部分
Care Data是一个纯粹的面向对象框架,可用于管理实体以及实体之间的关联关系的持久化,也就是我们通常所指的数据持久化。Care Data底层的持久化存储方式可以是SQLite数据库,也可以是XML文档,甚至可以直接以内存作为持久化存储设备。Care Data的核心概念是实体。实体是由Care Data管理的模型对象,它必须是NSManagedObject类或其子类的实例。实体与实体之间存在1-1、1-N、N-N、的关联关系,整个应用的所有实体以及实体之间的关联关系被称为托管对象模型NSManagedObiectModel。Care Data的核心对象是托管对象上下文NSManagedObjectContext,所有实体都处于托管对象上下文管理中,Care Data应用对实体所做的任何增、删、查、改操作都必须通过托管对象上下文来完成。开发者开发的应用程序需要通过NSMannagedObjectContext对实体进行增、删、查、改操作,而NSMannagedObjectContext底层与持久化存储协调衔接,持久化存储协调器则负责管理底层的存储形式比如:SQLite。Care Data应用中的核心API有如下几个。
托管对象模型NSManagedObiectModel:该对象负责管理整个应用的所有实体以及实体之间的关联关系。当开发者使用Xcode的图形界面设计了实体与实体的关联关系之后,需要使用该对象来加载、管理应用的托管对象模型。
持久化存储协调器NSPeristentStoreCoordinator:负责管理底层的存储文件,例如SQLite数据库等。
托管对象上下文NSManagedObjectContext:该对象是Care Data的核心对象,应用对实体所做的任何增、删、查、改操作都必须通过该对象来完成。
实体描述NSEntityDescription:该对象代表了关于某个实体的描述信息,从某种程度来说,该对象相当于实体的抽象。实体描述定义了该实体的名字、实体的实现类,并用一个集合定义了该实体包含的所有属性。
抓取请求NSFetchRequest:该对象封装了查询实体的请求,包括程序需要查询哪些实体、查询条件、排序规则等。抓取请求定义了本次查询的实体的名字、抓取请求的查询条件,通过NSPredicate来表示,并用一个NSArray集合定义了所有的排序规则。
熟悉以上几点之后,使用Core Data持久化操作的步骤大致如下。
创建NSManagedObiectModel对象来加载管理应用的托管对象模型。
以NSManagedObiectModel对象为基础,根据实际需要创建NSPeristentStoreCoordinator对象,该对象确定Core Data底层数据的存储形式。
以NSManagedObiectModel对象为基础,创建NSMannagedObjectContext,该对象是Core Data进行持久化访问的核心对象。
对于普通的增、删、查、改操作,需要分别先创建实体、删除实体、修改实体,然后调用NSMannagedObjectContext对象的save:方法将这些修改保存到底层存储设备。
如果要执行查询,则需要先创建NSFetchRequest对象,再调用NSMannagedObjectContext的executeFetchRequest:error:方法执行查询,该方法返回所有匹配条件的实体组成的NSArray。
2.手动配置环境
iOS允许在创建项目时勾选“Use Core Data”复选框,通过该方式创建的项目已经完成了所有Core Data必须资源的初始化,但此处并不打算使用这种方式来初始化Core Data项目,而是选择从一个Empty Application开始,手动初始化Core Data项目,这样便于大家真正理解Care Data项目需要初始化哪些资源。下面我们将开始把这个Empty Application项目一步步改造成Core Data项目。具体步骤如下:
为该项目添加CoreData.framework框架。
为该项目添加一个实体模型文件。单击Xcode主菜单的"File"---&"New"---&"File"菜单项,具体如下图:
careData01.png
在AppDelegate中初始化Core Data应用必须的核心API对象:NSManagedObiectModel、NSPeristentStoreCoordinator、NSManagedObjectContext修改应用程序委托类的接口部分,在接口部分定义上面3个核心API的属性,并增加一个对NSManagedObjectContext对象执行存储的方法、一个获取应用Docouments目录下的方法。下面是修改后的接口部分代码。
AppDelegate.h
#import &UIKit/UIKit.h&
#import &CoreData/CoreData.h&
@interface AppDelegate : UIResponder &UIApplicationDelegate&
@property (strong, nonatomic) UIWindow *
// 定义Core Data的3个核心API的属性
@property (readonly, strong, nonatomic) NSManagedObjectContext*
managedObjectC
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectM
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator*
persistentStoreC
- (void)saveC
- (NSURL *)applicationDocumentsD
接下来在AppDelegate.m中实现部分进行修改,初始化对象,并实现saveContext方法,其中applicationDocumentsDirectory是一个非常简单的方法,用于获取应用Docouments目录AppDelegate.m
@synthesize managedObjectContext = _managedObjectC
@synthesize managedObjectModel = _managedObjectM
@synthesize persistentStoreCoordinator = _persistentStoreC
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
return YES;
- (void)applicationWillTerminate:(UIApplication *)application
// 当应用被中断时候,将所有托管上下文中数据保存起来
[self saveContext];
- (void)saveContext
NSError *error =
// 获取应用的托管对象上下文
NSManagedObjectContext *managedObjectContext = self.managedObjectC
if (managedObjectContext != nil)
// 如果托管对象上下文中包含了未保存的修改,执行保存,如果保存失败记录错误信息
if ([managedObjectContext hasChanges] &&
![managedObjectContext save:&error])
NSLog(@"保存出现错误:%@, %@", error, [error userInfo]);
// 初始化应用的托管对象上下文。
- (NSManagedObjectContext *)managedObjectContext
// 如果_managedObjectContext已经被初始化过,直接返回该对象
if (_managedObjectContext != nil) {
return _managedObjectC
// 获取持久化存储协调器
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
// 如果持久化存储协调器不为nil
if (coordinator != nil)
// 创建NSManagedObjectContext对象
_managedObjectContext = [[NSManagedObjectContext alloc] init];
// 为NSManagedObjectContext对象设置持久化存储协调器
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectC
- (NSManagedObjectModel *)managedObjectModel
// 如果_managedObjectModel已经被初始化过,直接返回该对象
if (_managedObjectModel != nil) {
return _managedObjectM
// 获取实体模型文件对应的NSURL
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"FKModel"
withExtension:@"momd"];
// 加载应用的实体模型文件,并初始化NSManagedObjectModel对象
_managedObjectModel = [[NSManagedObjectModel alloc]
initWithContentsOfURL:modelURL];
return _managedObjectM
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
// 如果_persistentStoreCoordinator已经被初始化过,直接返回该对象
if (_persistentStoreCoordinator != nil) {
return _persistentStoreC
// 获取SQLite数据库文件的存储目录
NSURL *storeURL = [[self applicationDocumentsDirectory]
URLByAppendingPathComponent:@"Books.sqlite"];
NSError *error =
// 以持久化对象模型为基础,创建NSPersistentStoreCoordinator对象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
// 设置持久化存储协调器底层采用SQLite存储机制,如果设置失败记录错误信息
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil URL:storeURL options:nil error:&error])
NSLog(@"设置持久化存储失败:%@, %@", error, [error userInfo]);
return _persistentStoreC
// 获取应用的Documents目录
- (NSURL *)applicationDocumentsDirectory
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
到此Core Data所依赖的环境基本上已经搭建完毕,应用执行增、删、查、改操作直接调用managedObjectContext方法即可操作。
3.设计实体模型
Xcode中找到我们创建的Core Data文件,打开实体模型开始编辑,具体如下图:
coredata02.png
下面我们添加一个简单的实体,点击上图走下角的Add Entity,系统将会在ENTITIES列表下添加一个实体,将该实体重命名为项目所需的名字,此处为Bison
PS长按Add Entity将会显示Add Entity、Add Fetch Request、Add Configuration列表,可供选择添加实体、抓取请求、配置。
选中Bison实体,通过点击上图右下角的Add Attribute按钮,系统将会为该Bison实体添加一个属性,将该属性重命名所需的名字,此处重命名name,并为该属性选择类型,在此选String类型,注意:此处命名首字母不能大写哦。
PS长按Add Attribute将会显示Add Attribute、Add Relationship、Add Configuration、Add Fetch Property列表,可供选择添加属性、关联关系、抓取属性,也可以通过 + 、—来添加与删除。
重复上面的操作增加一个birthDay的属性,改属性为date类型。实体设计完后,如下图:
coredata03.png
然后单击Xcode主菜单的Editor--&Create NSManagedObject Subclass菜单项,如果系统包含俩个以上的实体,Xcode将会弹出一个对话框让选择腰围哪些实体生成NSManagedObject的子类,然后弹出对话框让选择NSManagedObject的子类的存储路径。选完之后Create按钮即可。经过上面的操作,为实体模型添加一个简单的Bison实体,该实体包含俩个属性,单不包含任何关联关系。
4.Core Data数据的增删查改
获取托管对象上下文NSManagedObjectContext之后,接下来即可通过该对象来执行增、删、查、改操作。
添加实体添加实体的步骤如下:调用NSEntityDescription的insertNewObjectForEntityForName:inManagedObjectContext:静态方法添加新实体。该方法的第1个参数为实体名,第2个参数为NSManagedObjectContext对象。为新实体设置属性。调用NSManagedObjectContext对象的save:方法执行保存。如下代码片段:
// 控制Core Data在托管对象上下文中创建一个新实体
Bison* bison = [NSEntityDescription
insertNewObjectForEntityForName:@"Bison"
inManagedObjectContext:self.appDelegate.managedObjectContext];
// 为新实体设置属性
bison.name = @"linbin";
bison.birth_Day = [NSDate date];
// 定义一个NSError对象,用于接受错误信息
// 设置完实体属性之后,调用托管对象上下文的`save:`方法将实体写入数据库,如果保存成功
if ([self.appDelegate.managedObjectContext save:&error])
[[[UIActionSheet alloc] initWithTitle:@"保存成功" delegate:nil
cancelButtonTitle:@"确定" destructiveButtonTitle:nil
otherButtonTitles: nil] showInView:self.view];
NSLog(@"保存FKEvent实体出错: %@,%@" , error ,[error userInfo]);
删除实体删除实体的步骤如下:首先获取要删除的实体,然后调用NSManagedObjectContext对象的deleteObject:方法删除实体。最后调用NSManagedObjectContext对象的save:方法执行保存。如下代码:
// 获取将要删除的实体
Bison* deleteEvent = .....;
// 从托管对象上下文中删除指定对象
[self.appDelegate.managedObjectContext deleteObject:deleteEvent];
// 保存删除操作,如果出现错误,显示错误信息
if (![self.appDelegate.managedObjectContext save:&error])
NSLog(@"删除FKEvent实体出错:%@,%@",error,[error userInfo]);
修改实体修改实体的步骤如下:首先获取要修改的实体,必须处于NSManagedObjectContext管理下的实体;然后修改实体的属性;再调用NSManagedObjectContext对象的save:方法执行保存。如下代码:
// 获取将要修改的实体
Bison* updateEvent = .....;
//修改实体的属性
//定义一个NSError对象,用于接收错误信息
// 保存修改操作,如果出现错误,显示错误信息
if (![self.appDelegate.managedObjectContext save:&error])
NSLog(@"删除FKEvent实体出错:%@,%@",error,[error userInfo]);
查询实体查询实体的步骤如下:首先创建NSFetchRequest对象。然后通过NSEntityDescription对象设置NSFetchRequest对象将要抓取的实体。如果需要对抓取结果进行筛选,则需要通过NSPredicate对象设置筛选条件。如果需要对结果进行排序,还需要为NSFetchRequest添加多个NSSortDescriptor对象。再调用NSManagedObjectContext对象的executeFetchRequest:error:方法执行查询,该查询方法将会返回所有符合条件的实体组成的NSArray集合。如下代码:
// 创建抓取数据的请求对象
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// 设置要抓取哪种类型的实体
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Bison"
inManagedObjectContext:self.appDelegate.managedObjectContext];
// 设置抓取实体
[request setEntity:entity];
NSError *error =
// 执行抓取数据的请求,返回符合条件的数据
eventArray = [[self.appDelegate.managedObjectContext
executeFetchRequest:request error:&error] mutableCopy];
基本的方法到此就结束了,具体的详情可以下载Demo查看
好文推荐:
原文地址:
如对你有帮助,请不要吝惜你的star和喜欢哦!
技术交流群:(免费)
.8/人付费)
版权归(C)Bison所有 如需转载请保留原文超链接地址!否则后果自负!
来个吉利的数字,激励一下Bison
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
如果你是程序员,或者有一颗喜欢写程序的心,喜欢分享技术干货、项目经验、程序员日常囧事等等,欢迎投稿《程序员》专题。
专题主编:小...
· 140857人关注
分享 iOS 开发的知识,解决大家遇到的问题,讨论iOS开发的前沿,欢迎大家投稿~
· 24082人关注
· 5801人关注
来个吉利的数字,激励一下Bison
选择支付方式:

我要回帖

更多关于 nspathstore2 的文章

 

随机推荐