学习了NSFetchedResultsController。才深深的体会到coredata的牛逼之处。原来Apple公司弄个新技术。不是平白无故的去弄,会给代码执行到来非常大的优点。coredata不仅能让我们大大的降低代码量。还最大化的提高执行效率。

就拿NSFetchedResultsController来说吧,他是和UITableView搭配使用的。能够最大化的提高UITableView的UI更新效率,比方我们删除一个东西,仅仅须要运行删除数据库里面的一条信息,然后通过配置NSFetchedResultsController的delegate方法,它自己主动会找到我们删除的那条信息。然后自己主动更新UI。最重要的时它不是总体的去更新UITableView,他是仅仅操作了须要删除的哪一个。这就是他的伟大之处。

以下看看我写的这个Demo吧

文件结构:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlqdW55dWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

将数据库中得数据放到缓冲区中:

<span style="font-size:14px;">- (void)viewDidLoad
{
[super viewDidLoad]; NSFetchRequest * request = [[NSFetchRequest alloc] init];
NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];
[request setEntity:desption]; NSSortDescriptor * desciptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObjects:desciptor, nil]]; //在CoreData为UITableView提供数据的时候。使用NSFetchedReslutsController能提高体验,由于用NSFetchedReslutsController去读数据的话,能最大效率的读取数据库,也方便数据变化后更新界面。
//当我们设置好这个fetch的缓冲值的时候,我们就完毕了创建 NSFetchedRequestController 而且将它传递给了fetch请求,可是这种方法事实上还有下面几个參数:
// 对于managed object 内容,我们值传递内容。 //sectionnamekeypath同意我们依照某种属性来分组排列数据内容。
//文件名称的缓存名字应该被用来处理不论什么反复的任务,比方说设置分组或者排列数据等。
NSFetchedResultsController * resultController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[CoreDataManage GetManagedObjectContext] sectionNameKeyPath:nil cacheName:nil];
resultController.delegate = self;
self.fetchController = resultController;
NSError * error = nil; //操作我们的 fetchedResultsController 而且运行performFetch 方法来取得缓冲的第一批数据。
if ([self.fetchController performFetch:&error])
{
NSLog(@"success");
// NSLog(@"=======%@",[self.fetchController])
}
else
{
NSLog(@"error = %@",error);
}
}
</span>

配置UITableView

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//section配置
// return [[self.fetchController sections] count]; //row配置
if ([[self.fetchController sections] count] > 0) {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
else
{
return 0;
}
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * mark = @"markIdentifer";
ContentCell * cell = [tableView dequeueReusableCellWithIdentifier:mark];
if (cell == nil)
{
cell = [[ContentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:mark];
} Student * stu = (Student *)[self.fetchController objectAtIndexPath:indexPath];
[cell showModel:stu];
return cell;
}

配置NSFetchedResultsController的delegate

<span style="font-size:14px;">//当数据发生变化时,点对点的更新tableview,这样大大的提高了更新效率
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch (type) {
case NSFetchedResultsChangeInsert:
[self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
{
[self.contentTableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
[self.contentTableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:newIndexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
}
break;
case NSFetchedResultsChangeUpdate:
{
ContentCell * cell1 = (ContentCell *)[self.contentTableView cellForRowAtIndexPath:indexPath];
Student * stu = (Student *)[controller objectAtIndexPath:indexPath];
[cell1 showModel:stu];
}
break; default:
break;
}
} //点对点的更新section
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) { case NSFetchedResultsChangeInsert:
[self.contentTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break; case NSFetchedResultsChangeDelete:
[self.contentTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
} //此方法运行时,说明数据已经发生了变化。通知tableview開始更新UI
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.contentTableView beginUpdates];
} //结束更新
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.contentTableView endUpdates];
}</span><span style="font-size:18px;">
</span>

加入一个删除button的操作。查看效果

<span style="font-size:14px;">-(NSArray *)searchResult
{
NSFetchRequest * request = [[NSFetchRequest alloc] init];
NSEntityDescription * desption = [NSEntityDescription entityForName:TABLE_NAME inManagedObjectContext:[CoreDataManage GetManagedObjectContext]];
[request setEntity:desption]; NSError * error = nil;
NSArray * result = [[CoreDataManage GetManagedObjectContext] executeFetchRequest:request error:&error];
if (!error)
{
[result enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOL *stop) {
NSLog(@"--%d,%@,%@,%@,%@--/n",idx,obj.studentnumber,obj.name,obj.age,obj.gender);
}]; }
else
{
NSLog(@"error seach = %@",error);
}
return result;
} -(IBAction)delete:(id)sender
{
NSArray * arr = [self searchResult];
__block Student * deletemp ;
[arr enumerateObjectsUsingBlock:^(Student * obj, NSUInteger idx, BOOL *stop) {
if ([obj.studentnumber intValue] == 2)
{
deletemp = obj;
*stop = YES;
}
}];
if (deletemp)
{
[[CoreDataManage GetManagedObjectContext] deleteObject:deletemp];
NSLog(@"====ok===delete");
}
}</span><span style="font-size:18px;">
</span>

如今编译执行你的应用的话。表面上看起来应该都是一样的,可是假设你看看控制台的话,惊人的事情正在发生:

SELECT 0, t0.Z_PK FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK
ORDER BY t1.ZCLOSEDATE DESC
total fetch execution time: 0.0033s for 234 rows. SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZSTATE, t0.ZCITY,
t0.ZDETAILS FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK WHERE
t0.Z_PK IN (?,?,? ,?,?,?,?,? ,? ,? ,?,?,? ,? ,? ,?,?,?,?,?)
ORDER BY t1.ZCLOSEDATE DESC LIMIT 20
total fetch execution time: 0.0022s for 20 rows. SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZNAME, t0.ZSTATE, t0.ZCITY,
t0.ZDETAILS FROM ZFAILEDBANKINFO t0 LEFT OUTER JOIN
ZFAILEDBANKDETAILS t1 ON t0.ZDETAILS = t1.Z_PK WHERE
t0.Z_PK IN (?,? ,? ,?,?,?,? ,?,?,?,?,? ,? ,? ,?,?,?,? ,?,?)
ORDER BY t1.ZCLOSEDATE DESC LIMIT 20
total fetch execution time: 0.0017s for 20 rows.

你能够看到, NSFetchedResultsController 正在从 FailedBankInfo中依照之前设置的顺序取得大量的ID,依据UITableView的情况每次仅仅缓冲一定数量的数据。

比我们直接操控sqlite数据库方便多了。

源代码下载

CoreData使用方法二:NSFetchedResultsController实例操作与解说的更多相关文章

  1. 登录操作(方法二:for与else搭配)

    登录操作(方法二:for与else搭配) user_name="star"passwoed='123' count=0for i in range(3): u_username=i ...

  2. 免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)

    在生活中有一种东西几乎已经快要成为我们的另一个电子”身份证“,那就是二维码.无论是在软件开发的过程中,还是在普通用户的日常中,几乎都离不开二维码.二维码 (dimensional barcode) , ...

  3. Android抓包方法(二)之Tcpdump命令+Wireshark

    Android抓包方法(二) 之Tcpdump命令+Wireshark 前言 做前端测试,基本要求会抓包,会分析请求数据包,查看接口是否调用正确,数据返回是否正确,问题产生是定位根本原因等.学会抓包分 ...

  4. DotNet二维码操作组件ThoughtWorks.QRCode

    DotNet二维码操作组件ThoughtWorks.QRCode 在生活中有一种东西几乎已经快要成为我们的另一个电子"身份证",那就是二维码.无论是在软件开发的过程中,还是在普通用 ...

  5. python运维开发(二十)----models操作、中间件、缓存、信号、分页

    内容目录 select Form标签数据库操作 models操作F/Q models多对多表操作 Django中间件 缓存 信号 分页 select Form标签补充 在上一节中我们可以知道Form标 ...

  6. ExtJS学习--------Ext.Element中的经常使用事件和其它重要的方法学习(实例)

    经常使用事件: 其它重要方法: 详细实例:(实例结果能够将相应的代码取消凝视进行測试) Ext.onReady(function(){ Ext.create('Ext.panel.Panel',{ t ...

  7. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  8. Vue源码分析(二) : Vue实例挂载

    Vue源码分析(二) : Vue实例挂载 author: @TiffanysBear 实例挂载主要是 $mount 方法的实现,在 src/platforms/web/entry-runtime-wi ...

  9. day 70 Django基础五之django模型层(二)多表操作

    Django基础五之django模型层(二)多表操作   本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...

随机推荐

  1. 如果把父组件的数据实时的传递到子组件:用watch

    1.在子组件使用watch来监听传递给子组件的数据,然后更新子组件的数据. 2.watch和computed结合使用效果非常好. 参考链接:https://blog.csdn.net/zhouweix ...

  2. v-for实现循环嵌套

    <!DOCTYPE html> <html lang="en"> <head> <title></title> < ...

  3. ArcGIS在线帮助的使用指南

    一直感觉ArcGIS的在线帮助就是鸡肋,没想到网络常见的所谓的高大上的博文,也不过是对GIS 在线帮助的拷贝,或者简单修改而已.其实ArcGIS的在线帮助包含了以下几个很好用的模块: 备注 ArcGI ...

  4. c++ builder firemonkey 实现填充椭圆

    相信同类Delphi 类似文章非常多了,这里我用c++ builder firemonkey 实现填充椭圆 本例主要在FormPaint实现,当然你想在Image1->Bitmap->Ca ...

  5. Kaggle实战分类问题2

    Kaggle实战之二分类问题 0. 前言 1. MNIST 数据集 2. 二分类器 3. 效果评测 4. 多分类器与误差分析 5. Kaggle 实战 0. 前言 “尽管新技术新算法层出不穷,但是掌握 ...

  6. Scala入门到精通——第十九节 隐式转换与隐式參数(二)

    作者:摇摆少年梦 配套视频地址:http://www.xuetuwuyou.com/course/12 本节主要内容 隐式參数中的隐式转换 函数中隐式參数使用概要 隐式转换问题梳理 1. 隐式參数中的 ...

  7. OC的DES加密,使与java的Cipher类用DES/CBC/PKCS5Padding方式的加密结果同样

    问题说明: 近期用到DES加密,而且要与java的Cipher类加密的结果保持一致.没研究过java的Cliper,但工作中Cipher依据DES/CBC/PKCS5Padding加密方式生成了一个字 ...

  8. UVA 10943 - How do you add? 递推

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  9. UVA 11987 - Almost Union-Find

    第一次交TLE,说好的并查集昂. 好吧我改.求和.个数 在各个步骤独立算.. 还是TLE. 看来是方法太慢,就一个数组(fa),移动的话,移动跟结点要遍历一次 T T 嗯,那就多一个数组. 0.189 ...

  10. mysql三种带事务批量插入

    原文:mysql三种带事务批量插入 c#之mysql三种带事务批量插入 前言 对于像我这样的业务程序员开发一些表单内容是家常便饭的事情,说道表单 我们都避免不了多行内容的提交,多行内容保存,自然要用到 ...