CoreData数据库虽然可以和tableview或者UITableViewController一起使用将数据显示在表格上,但是在准备数据的时候,这种方式需要用一个可变数组来装从数据库一次性取出来的所有数据,然后通过操作这个数组来显示数据再表格上,从内存的优化和性能上来说并不是很好;这里,介绍一种新的抓取数据的方式,苹果公司为了进一步优化内存,创建了一个从数据库抓取数据的控制器NSFetchedResultsController,它能从CoreData中一批一批的抓取数据并存放起来,然后通过操作它来将数据显示在表格中,极大的优化了内存;与此同时,这个控制器还提供了一个<NSFetchedResultsControllerDelegate>协议,通过该控制器的代理可以实现数据的实时动画更新(删除、插入、修改)。CoreData数据库和UITableViewController以及NSFetchedResultsController一起使用,具有很强大的功能,是一个很不错的方式,推荐掌握这门技术。以下就具体的例子来介绍:

要求:创建一个实体对象Book数据库表,多次设置它的属性,并将它显示在表格中,显示后进行的操作有:(1)仅仅进行删除对象、(2)在删除时同时又插入两条对象信息、(3)删除时修改它的属性并再从新显示该对象

前期的创建数据库表的具体步骤:

1、创建新项目时,勾选Use Core Data,生成CoreData____NSFetchResultController.xcdatamodel文件,此时AppDelegate类中自动封装了sqlite的大量方法和需要的managedObjectContext、managedObjectModel、persistentStoreCoordinator三个对象等;

     

2、点击该文件,进入设置面板,点击左下角的Add Entity,创建实体对象并设置它的类名,同时在Attribute处添加该实体对象的属性;

      

3、选中该实体对象,点击模拟器菜单栏的Editor下的create NSManagedObjectSubclass..,自动生成实体对象的类Book.h和Book.m文件,类中自动生成了实体对象的所有属性;

         

4、再一次进入设置面板,点击右下角的style,可以查看成功创建的数据库表。

     

5、进入故事板Storyboard中,删除viewController控制器和它的类,重新拖入一个新的视图控制器和一个表格视图TableView;

6、新建一个新的类为BookTableViewController继承自UITableViewController,并将上面新拖入的视图控制器关联这个类即可。好了,前期工作完成。

                 

接下来即时具体的代码操作了:

在AppDelegate类的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中奖数据存储到数据库:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

     //读取偏好设置,使测试数据只插入一次
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
self.isInserted = [userDefaults boolForKey:@"isInserted"]; if(!self.isInserted)
{
[self addBookWithTitle:@"《红楼梦》" andPrice:@50.5];
[self addBookWithTitle:@"《西游记》" andPrice:@48.5];
[self addBookWithTitle:@"《水浒传》" andPrice:@67.5];
[self addBookWithTitle:@"《三国演义》" andPrice:@70.0];
[self addBookWithTitle:@"《资治通鉴》" andPrice:@79.0];
[self addBookWithTitle:@"《本草纲目》" andPrice:@59.0];
[self addBookWithTitle:@"《二十四史》" andPrice:@98.0]; } //设置偏好设置
[userDefaults setBool:YES forKey:@"isInserted"];
[userDefaults synchronize]; return YES;
}

//将设置上面对象属性的方法封装起来

 -(void)addBookWithTitle:(NSString*)title andPrice:(NSNumber*)price
{
//取出实体对象
Book *book = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([Book class]) inManagedObjectContext:self.managedObjectContext]; //设置属性
book.title = title;
book.price = price; //保存数据到持久层
[self saveContext]; }

在BookTableViewController.m文件中:

//导入头文件,实现协议和定义属性

 #import "BookTableViewController.h"
#import "AppDelegate.h"
#import "Book.h" @interface BookTableViewController ()<NSFetchedResultsControllerDelegate>
@property (strong,nonatomic)NSFetchedResultsController *fetchResultVC;
@property (strong,nonatomic)NSManagedObjectContext *managedObjectContext;

//NSFetchedResultsController从数据库抓取数据

 - (void)viewDidLoad {
[super viewDidLoad]; //创建应用程序对象
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate]; self.managedObjectContext = appDelegate.managedObjectContext; //fetchResultVC获取CoreData中的数据
NSError *error = nil;
[self.fetchResultVC performFetch:&error];
if(error)
{
NSLog(@"获取数据失败");
} }
//懒加载创建NSFecthedResultsController控制器对象
 -(NSFetchedResultsController*)fetchResultVC
{
if(!_fetchResultVC)
{
//创建请求对象
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([Book class])]; //批处理,每次从数据库中抓取的数量
fetchRequest.fetchBatchSize = ; //设置排序对象
NSSortDescriptor *priceSort = [NSSortDescriptor sortDescriptorWithKey:@"price" ascending:YES];
[fetchRequest setSortDescriptors:@[priceSort]]; //创建fetchResultVC
_fetchResultVC = [[NSFetchedResultsController alloc]initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"book"]; //设置fetchResultVC的代理
_fetchResultVC.delegate = self;
}
return _fetchResultVC;
}

#pragma mark - Table view data source//显示表格内容

//组数

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.fetchResultVC.sections.count;
}

//行数

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id<NSFetchedResultsSectionInfo> sectionInfo = [self.fetchResultVC.sections objectAtIndex:section]; return [sectionInfo numberOfObjects];
}

//将设置行内容的方法封装,调用它设置cell内容

 -(void)configCell:(UITableViewCell*)cell indexPath:(NSIndexPath*)indexPath
{
Book *book = [self.fetchResultVC objectAtIndexPath:indexPath];
cell.textLabel.text = book.title;
cell.detailTextLabel.text = [NSString stringWithFormat:@"$%@",book.price];
}
 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//1.根据reuseIdentifier,先到对象池中去找重用的单元格对象
static NSString *reuseIdentifier = @"bookCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
//2.如果没有找到,自己创建单元格对象
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:reuseIdentifier];
}
//3.设置单元格对象的内容
[self configCell:cell indexPath:indexPath];
return cell;
}

//设置单元格的编辑与否

 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}

//只进行删除数据

  Book *book = [self.fetchResultVC objectAtIndexPath:indexPath];//获取实体对象
NSError *error = nil; //删除数据
//从CoreData数据库删除数据
[self.managedObjectContext deleteObject:book];//从上下文是删除该实体对象
[self.managedObjectContext save:&error];//保存上下文

//删除数据时,同时新插入插入数据

   AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
[appDelegate addBookWithTitle:@"《狂人日记》" andPrice:@20.0];
[appDelegate addBookWithTitle:@"《洗冤集录》" andPrice:@24.5];

//删除数据时,修改数据并显示

 //在删除数据时,修改它的数据并更新
book.price = @([book.price doubleValue] + );
[self.managedObjectContext save:&error];
if(error)
{
NSLog(@"删除失败");
}

#pragma mark -<NSFetchedResultsControllerDelegate>代理方法,更新变化后的表格信息

 //表格开始更新
-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
//尽心更新处理
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
if(type == NSFetchedResultsChangeDelete) //删除数据
{
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else if(type == NSFetchedResultsChangeInsert) //插入数据
{
[self.tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
else if(type == NSFetchedResultsChangeUpdate) //更新(修改)数据
{ UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
[self configCell:cell indexPath:indexPath]; [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
//表格更新结束
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}

演示结果如下:

没有进行任何操作时:                       选中单元格往左滑动,删除数据时

        

删除数据时,同时新插入两个对象                        没删除一次,对象的属性价格就发生了改变

          

 

iOS:CoreData数据库的使用四(数据库和UITableViewController以及NSFetchedResultsController一起使用)的更多相关文章

  1. iOS CoreData技术学习资源汇总

    一.CoreData学习指引 1. 苹果官方:Core Data Programming Guide 什么是CoreData? 创建托管对象模型 初始化Core Data堆栈 提取对象 创建和修改自定 ...

  2. QF——iOS中的数据库操作:SQLite数据库,第三方封装库FMDB,CoreData

    SQLite数据库: SQLite是轻量级的数据库,适合应用在移动设备和小型设备上,它的优点是轻量,可移植性强.但它的缺点是它的API是用C写的,不是面向对象的.整体来说,操作起来比较麻烦.所以,一般 ...

  3. iOS CoreData (二) 版本升级和数据库迁移

    前言:最近ChinaDaily项目需要迭代一个新版本,在这个版本中CoreData数据库模型上有新增表.实体字段的增加,那么在用户覆盖安装程序时就必须要进行CoreData数据库的版本升级和旧数据迁移 ...

  4. 使用iOS原生sqlite3框架对sqlite数据库进行操作

    摘要: iOS中sqlite3框架可以很好的对sqlite数据库进行支持,通过面向对象的封装,可以更易于开发者使用. 使用iOS原生sqlite3框架对sqlite数据库进行操作 一.引言 sqlit ...

  5. iOS学习36数据处理之SQLite数据库

    1. 数据库管理系统 1> SQL语言概述 SQL: SQL是Structured Query Language(结构化查询语言)的缩写.SQL是专为数据库而建立的操作命令集, 是一种功能齐全的 ...

  6. 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  7. GZFramwork数据库层《四》单据主从表增删改查

    同GZFramwork数据库层<三>普通主从表增删改查 不同之处在于:实例 修改为: 直接上效果: 本系列项目源码下载地址:https://github.com/GarsonZhang/G ...

  8. 2014-11-9------- 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  9. 【2017-03-09】SQL Server 数据库基础、四种约束

    一.数据库和内存的区别 数据库:一些存储在硬盘上的数据文件 内存:计算机临时存储的一些数据 二.常用数据库 .Net - SQL Server PHP - MySql Java - Oreacl 三. ...

随机推荐

  1. Java虚拟机四:垃圾回收算法与垃圾收集器

    在Java运行时的几个数据区域中,程序计数器,虚拟机栈,本地方法栈3个区域随着线程而生,随线程而灭,因此这几个区域的内存分配和回收具有确定性,不需要过多考虑垃圾回收问题,因为方法结束或者线程结束时,内 ...

  2. SQL2:数据操作

    1.数据插入: 1)插入表中: INSERT INTO TABLE_NAME VALUE('value1','value2',....); 2)从另一个表中插入数据: INSERT INTO TABL ...

  3. jsp有哪些内置对象作用分别是什么 分别有什么方法?

    JSP共有以下9个内置的对象: request 用户端请求,此请求会包含来自GET/POST请求的参数 response 网页传回用户端的回应 pageContext 网页的属性是在这里管理 sess ...

  4. Hibernate 过滤查询(hibernate过滤器的使用)

    我们在开发过程中过滤查询使用的还是挺多的,今天来学习一下hibernate的过滤器的使用,首先学习在配置文件中如何使用,然后再介绍如何使用注解配置. 1.使用配置文件配置过滤器  1)首先我们使用my ...

  5. BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

    http://www.lydsy.com/JudgeOnline/problem.php?id=4036 http://blog.csdn.net/lych_cys/article/details/5 ...

  6. [GCJ2017R3]Cooclement

    题目大意: 一种数列按照如下方式变化: 新数列第i位等于原数中数字i的出现次数. 变化过程中数列长度不变. 例如数列12的变化过程为12-11-20-01-10. 现在告诉你一个数列x,请求出x可能是 ...

  7. Java并发(九):重入锁 ReentrantLock

    先做总结: 1.为什么要用ReentrantLock? (1)ReentrantLock与synchronized具有相同的功能和内存语义: (2)synchronized是重量级锁,性能不好.Ree ...

  8. 【8.23校内测试】【贪心】【线段树优化DP】

    $m$的数据范围看起来非常有问题??仔细多列几个例子可以发现,在$m<=5$的时候,只要找到有两行状态按位$&$起来等于$0$,就是可行方案,如果没有就不行. #include<i ...

  9. 洛谷P1341 最受欢迎的奶牛

    题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的.奶牛之间的“喜欢”是可以传递的——如果A喜 欢B,B喜欢C,那么A也喜欢C ...

  10. Codeforces Round #305 (Div. 1) B. Mike and Feet 单调栈

    B. Mike and Feet Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/547/pro ...