一 、NSManagedObjectContext

1、我们要想操作Core Data,首先需要一个NSManagedObjectContext
2、那我们如何获得Context呢:创建一个UIManagedDocument

二、UIManagedDocument

1、UIManagedDocument是一系列用于管理存储的机制:
  【将Core Data数据库放入某存储空间,相当于是管理core data 数据库的存储,所以我们只需要打开和存储】
2、那我们如何得到UIManagedDocument呢?如何在用户文档中创建一个UIDocument?

 //(1文件管理器能够给我们一个用户文件目录的URL
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; //(2然后加上我们想要的文档名
NSString *documentName = @“MyDocument”;
NSURL *url = [documentsDirectory URLByAppendingPathComponent:documentName];
//(3这个URL就是core data数据库存储的地方
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];

3、但是我们创建的这个文档还并不存在于我们的磁盘中,还需要存储到磁盘

 //(1先判断是否已经存在于磁盘
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[url path]];!
//(2.1如果已经存在于磁盘,则直接打开
[document openWithCompletionHandler:^(BOOL success) { /* block to execute when open */ }]; !
//(2.2否则还要先存储到磁盘
[document saveToURL:url forSaveOperation:UIDocumentSaveForCreating competionHandler:^(BOOL success) { /* block to execute when create is done */ }];

e.g.下面我们看一个综合了上面的具体的例子,如何通过UIManagedDocument得到NSManagedObjectContext:

 self.document = [[UIManagedDocument alloc] initWithFileURL:(URL *)url];
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[document openWithCompletionHandler:^(BOOL success) {
if (success) [self documentIsReady];
if (!success) NSLog(@“couldn’t open document at %@”, url);
}];
} else {
[document saveToURL:url forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if (success) [self documentIsReady];
if (!success) NSLog(@“couldn’t create document at %@”, url);
}];
}

然后我们在 documentIsReady做一些操作从而获得context:

 - (void)documentIsReady
{
/*对应的状态有:
UIDocumentStateClosed (还没有打开或者创建)
UIDocumentStateSavingError (completion handler保存没有成功)
UIDocumentStateEditingDisabled (重试)
UIDocumentStateInConflict(例如有其他人在使用更新,有冲突到等)*/ if (self.document.documentState == UIDocumentStateNormal) {
//如果成功的话,我们就获得了我们需要的context了,然后操作core data
NSManagedObjectContext *context = self.document.managedObjectContext;
}
}

4、注意的点
【但要注意的点1:上面UIManagedDocument的打开、关闭或者创建(存储)都是异步执行的】
【需要注意的点2: UIManagedDocument是自动保存的,我们也可以调用上面的自己保存,对应的关闭也是自动关闭的】
【需要注意的点3: UIManagedDocument是多实例的,也就是说可以多控制器同时操作,但对应的同时只有一个可写】

5、广播站:
比如我们在一个文档中修改了数据CoreData,但是同时 另一个并没有能马上看到,这是因为它们所用的Context不同,要想能看到需要使用NSNotiFication广播站

三、NSNotiFication广播站

1、如何注册一个广播

 - (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[center addObserver:self
selector:@selector(contextChanged:)
name:NSManagedObjectContextDidSaveNotification
object:document.managedObjectContext]; // don’t pass nil here!
}
- (void)viewWillDisappear:(BOOL)animated
{
[center removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:document.managedObjectContext];
[super viewWillDisappear:animated];
}

2、广播得到消息之后能做什么?如何在contextChanged里操作?

(1 可以取回我的所有对象

 - (void)contextChanged:(NSNotification *)notification
{
// notification.userInfo 返回给我们的是一个字典包含以下的key
NSInsertedObjectsKey //插入的对象数组
NSUpdatedObjectsKey // 有属性更改的对象数组
NSDeletedObjectsKey // 有删除的对象数组
}

(2 Merging changes:只要把notification传给它,它会自动帮我们把所有的变化合并到我们的context中
   - (void)mergeChangesFromContextDidSaveNotification:(NSNotification *)notification;

四、Core Data

上面的操作都完备,我们就可以对我们的数据库进行增删改的操作了
【这些操作是在内存中,不是在磁盘,但是别忘记了Document是自动保存的,所以最终还是会保存到磁盘的,只要文档保存了,Context就保存了】

1、插入

    NSManagedObjectContext *context = aDocument.managedObjectContext;
//实体的名称:@“EntityBook”,返回NSManagedObject对象【数据库所有对象都是它或者它的子类】
NSManagedObject *book = [NSEntityDescription insertNewObjectForEntityForName:@“EntityBook” inManagedObjectContext:context];
//设置属性
- (id)valueForKey:(NSString *)key;
- (void)setValue:(id)value forKey:(NSString *)key;
或者也可以用:valueForKeyPath:/setValue:forKeyPath

设置属性例如:
NSString *myThumbnail = book.thumbnailURL;
book.lastViewedDate = [NSDate date];
book.whoTook = ...; //这里的whoTook指的是另一张表的关联关系
book.whoTook.name = @“CS193p Instructor”;

2、删除

//(1要注意的是这也不是马上删除,而是需要在自动保存之后才会删除,但是引用到book的地方需要在这个操作之后设置为nil
[aDocument.managedObjectContext deleteObject:book];

//(2 这个方法通常放在类别中,用于删除操作之后的某些更新
- (void)prepareForDeletion{}

3、查询

(1 NSFetchRequest 提出请求从数据库请求对象
指定要取回的实体、指定取回的对象大小数量、NSSortDescriptors排序、NSPredicate谓词哪一些数据

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@“EntityBook”];
request.fetchBatchSize = 20;
request.fetchLimit = 100;
request.sortDescriptors = @[sortDescriptor];
request.predicate = ...;

(2 NSSortDescriptor 排序

 NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:@“title” //排序的键
ascending:YES //YES是按字母排序,NO是反字母排序
selector:@selector(localizedStandardCompare:)]; //在排序中的对比,这里的localizedStandardCompare 指代像Mac finder中的排序方式一般

(3 NSPredicate谓词

     NSString *serverName = @“IOS-”;
NSPredicate *predicate =
[NSPredicate predicateWithFormat:@“bookName contains %@”, serverName]; @“uniqueId = %@”, [flickrInfo objectForKey:@“id”]
@“name contains[c] %@”, (NSString *)
@“viewed > %@”, (NSDate *)
@“whoTook.name = %@”, (NSString *)
@“any photos.title contains %@”, (NSString *)
@“(name = %@) OR (title = %@)”
@“photos.@count > ”
@“photos.photo.title.length"
[propertyListResults valueForKeyPath:@“photos.photo.@avg.latitude”] // 复合谓词
NSArray *array = @[predicate1, predicate2];
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:array];

更多的使用可以查询:
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/KeyValueCoding/Articles/CollectionOperators.html.

demo请求的例子:

     NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@“Photographer”];
NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-**];
request.predicate = [NSPredicate predicateWithFormat:@“any photos.uploadDate > %@”, yesterday];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@“name” ascending:YES]]; NSManagedObjectContext *context = aDocument.managedObjectContext;
NSError *error;
NSArray *photographers = [context executeFetchRequest:request error:&error];

五. 生成实体的类

1、方法
Editor->Create NSManagedObject Subclass => 选择Model => 选择要生成的数据表EntityBook

2、可以修改这些系统生成的类?=> 最好不要,我们可以采用类别的方法,也就是Categories
【Categories类别可以添加方法到一个类,而不用创建它额的子类,你甚至不需要有该类的源代码】

六、Categories类别

【不能使用实例变量或者任何存储数据】
1、声明

 @interface EntityBook (AddOn)
- (NSString *)note;
@property (readonly) BOOL isOld;
@end

2、实现

 @implementation EntityBook (AddOn)
- (NSString *)note //要注意:note不是数据库表的属性,但是这里的bookName uploadDate是属性
{
NSString *bookNote = [NSString stringWithFormat:@"%@:lalalallal", self.bookName];
return bookNote;
}
- (BOOL)isOld //
{
return [self.uploadDate timeIntervalSinceNow] > -**;
}
@end

3、大多数情况下的实现

 @implementation EntityBook (Create)

 + (EntityBook *)bookWithData:(NSDictionary *)Data inManagedObjectContext:(NSManagedObjectContext *)context
{
EntityBook *book = ...; // 查看具体某一本书是否存在
if (!book)
{
book = [NSEntityDescription insertNewObjectForEntityForName:@“EntityBook” inManagedObjectContext:context];
}
return book;
}
@end

七、线程安全

1、NSManagedObjectContext并不线程安全,任何使用在下面的BLock里面去执行 它会对Context在安全队列中执行

[context performBlock:^{ or performBlockAndWait:
       //使用对Context做的事情,例如插入对象、查询等等
}];

八、NSFetchedResultsController

[使得Core Data和UITableViewController能够相辅相成。]

1、例如:

- (NSUInteger)numberOfSectionsInTableView:(UITableView *)sender

{

return [[self.fetchedResultsController sections] count];

}

- (NSUInteger)tableView:(UITableView *)sender numberOfRowsInSection:(NSUInteger)section

{

return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];

}

- (UITableViewCell *)tableView:(UITableView *)sender cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

UITableViewCell *cell = ...;

// 或者 Book *book = (Book *) ...

NSManagedObject *managedObject =  [self.fetchedResultsController objectAtIndexPath:indexPath];

return cell;

}

2、那么如何构建一个NSFetchedResultsController呢?

NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@“EntityBook”];

request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@“title” ...]];

//关联另一张表的查询,比如说作者表中的作者名称,作为我们book表的WhoTook

request.predicate = [NSPredicate predicateWithFormat:@“whoTook.name = %@”, authorName];

NSFetchedResultsController *frc = [[NSFetchedResultsController alloc]

initWithFetchRequest:(NSFetchRequest *)request

managedObjectContext:(NSManagedObjectContext *)context

sectionNameKeyPath:(NSString *)keyThatSaysWhichSectionEachManagedObjectIsIn

cacheName:@“MyPhotoCache”// 指定为nil的话,就不会执行缓存处理[永久性在磁盘中]:所以只针对总有相同FetChRequest的TableView

];

3、让NSFetchwsResultController和TableView关联起来有两种方式,一种是利用它实现所有UITableViewDataSource的东西

第二种就是设置委托:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject

atIndexPath:(NSIndexPath *)indexPath

forChangeType:(NSFetchedResultsChangeType)type

newIndexPath:(NSIndexPath *)newIndexPath

{

// 更新TableView[可以利用CoreDataTableViewController]

}

4、CoreDataTableViewController

OC开发_Storyboard——Core Data的更多相关文章

  1. ios开发:Core Data概述

    Core Data 概述 2005年的四月份,Apple 发布了 OS X 10.4,在这个版本中 Core Data 框架发布了.Core Data本身既不是数据库也不是数据库访问框架.相反,Cor ...

  2. OC开发_Storyboard——MapKit

    一.Core  Location 1.基本对象 @propertys: coordinate, altitude, horizontal/verticalAccuracy, timestamp, sp ...

  3. OC开发_Storyboard——iPad开发

    iPad开发(Universal Applications) 一.iPad 1.判断是否在iPad上 BOOL iPad = ([[UIDevice currentDevice] userInterf ...

  4. OC开发_Storyboard——AutoLayout

    一.autolayout 自动布局: 1. 设置所有视图框架的三种方法,可以通过代码创建也可以storyboard设置 = 规则 (1 蓝线+约束:(位置) 使用蓝线,根据蓝线拖动控件,只是告诉Xco ...

  5. OC开发_Storyboard——多线程、UIScrollView

    一.多线程 1.主队列:处理多点触控和所有UI操作(不能阻塞.主要同步更新UI) dispatch_queue_t mainQueue = dispatchg_get_main_queue(); // ...

  6. OC开发_Storyboard——UITableView

    一.tableView 1.datasource数据源 (1 构造每一个tableVIewCell的方法:cellForRowAtIndexPath,这里的 dequeueReusableCellWi ...

  7. OC开发_Storyboard——UIApplication和网络活动指示器

    一.UIApplication 只有一个实例: UIApplication *myApplication = [UIApplication sharedApplication]; 属性如果设置为YES ...

  8. OC开发_Storyboard——绘制和视图

    1.绘制 不要调用drawRect.调用setNeedsDisplay相当于告知系统视图需要重绘, 它会去调用drawRect,更新屏外缓冲器 2.UIBezierPath绘制图形,   设置图像op ...

  9. OC开发_Storyboard——block和动画

     一.协议 @optional :可选的 @requied :必须实现的  二.block 代码块 1. 以一个^开头,然后是参数,然后是一个大括号,包含我们的代码块 [aDictionary enu ...

随机推荐

  1. oracle权限详解

    一.权限分类:系统权限:系统规定用户使用数据库的权限.(系统权限是对用户而言). 实体权限:某种权限用户对其它用户的表或视图的存取权限.(是针对表或视图而言的). 二.系统权限管理:1.系统权限分类: ...

  2. C语言写的trim()函数

    C语言的标准库中缺少对字符串进行操作的trim()函数,使用起来有些不便,可以使用利用 strlen 和 isspace 函数以及指针来自己写一个. 1.strlen 函数 原型:extern int ...

  3. Hbase Rowkey设计

    转自:http://www.bcmeng.com/hbase-rowkey/ 建立Schema Hbase 模式建立或更新可以通过 Hbase shell 工具或者使用Hbase Java API 中 ...

  4. Hash表的表大小

    hash表的出现主要是为了对内存中数据的快速.随机的访问.它主要有三个关键点:Hash表的大小.Hash函数.冲突的解决. 这里首先谈谈第一点:Hash表的大小. Hash表的大小一般是定长的,如果太 ...

  5. C++中函数的返回值

    原文 [ 函数的返回值用于初始化在调用函数处创建的临时对象.在求解表达式时,如果需要一个地方储存其运算结果,编译器会创建一个没有命名的对象,这就是 临时对象.temporary object ] -- ...

  6. Navicat连接Oracle11g 错误的解决办法

    一.换成32位的Navicat!!! 二.去Oracle官网下载你要连接数据版本的client. 注意:需要下载两个文件,以11.2.0.4.0版本为例,需要下载 instantclient-sqlp ...

  7. 第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型

    第二百九十六节,python操作redis缓存-Hash哈希类型,可以理解为字典类型 Hash操作,redis中Hash在内存中的存储格式如下图: hset(name, key, value)name ...

  8. 第二百八十六节,MySQL数据库-MySQL事务操作(回滚)

    MySQL数据库-MySQL事务操作(回滚) 事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性. 举例:有这样一张表 从表里可以看出张 ...

  9. 介绍Unity中相机的投影矩阵与剪切图像、投影概念

    这篇作为上一篇的补充介绍,主要讲Unity里面的投影矩阵的问题: 上篇的链接写给VR手游开发小白的教程:(三)UnityVR插件CardboardSDKForUnity解析(二) 关于Unity中的C ...

  10. 【转】struts2.5框架使用通配符指定方法(常见错误)

    在学习struts框架时经常会使用到通配符调用方法,如下: <package name="shop" namespace="/" extends=&quo ...