iOS:CoreData数据库的使用四(数据库和UITableViewController以及NSFetchedResultsController一起使用)
2015-09-23 20:22
585 查看
CoreData数据库虽然可以和tableview或者UITableViewController一起使用将数据显示在表格上,但是在准备数据的时候,这种方式需要用一个可变数组来装从数据库一次性取出来的所有数据,然后通过操作这个数组来显示数据再表格上,从内存的优化和性能上来说并不是很好;这里,介绍一种新的抓取数据的方式,苹果公司为了进一步优化内存,创建了一个从数据库抓取数据的控制器NSFetchedResultsController,它能从CoreData中一批一批的抓取数据并存放起来,然后通过操作它来将数据显示在表格中,极大的优化了内存;与此同时,这个控制器还提供了一个<NSFetchedResultsControllerDelegate>协议,通过该控制器的代理可以实现数据的实时动画更新(删除、插入、修改)。CoreData数据库和UITableViewController以及NSFetchedResultsController一起使用,具有很强大的功能,是一个很不错的方式,推荐掌握这门技术。以下就具体的例子来介绍:
要求:创建一个实体对象Book数据库表,多次设置它的属性,并将它显示在表格中,显示后进行的操作有:(1)仅仅进行删除对象、(2)在删除时同时又插入两条对象信息、(3)删除时修改它的属性并再从新显示该对象
前期的创建数据库表的具体步骤:
1、创建新项目时,勾选UseCoreData,生成CoreData____NSFetchResultController.xcdatamodel文件,此时AppDelegate类中自动封装了sqlite的大量方法和需要的managedObjectContext、managedObjectModel、persistentStoreCoordinator三个对象等;
2、点击该文件,进入设置面板,点击左下角的AddEntity,创建实体对象并设置它的类名,同时在Attribute处添加该实体对象的属性;
3、选中该实体对象,点击模拟器菜单栏的Editor下的createNSManagedObjectSubclass..,自动生成实体对象的类Book.h和Book.m文件,类中自动生成了实体对象的所有属性;
4、再一次进入设置面板,点击右下角的style,可以查看成功创建的数据库表。
5、进入故事板Storyboard中,删除viewController控制器和它的类,重新拖入一个新的视图控制器和一个表格视图TableView;
6、新建一个新的类为BookTableViewController继承自UITableViewController,并将上面新拖入的视图控制器关联这个类即可。好了,前期工作完成。
接下来即时具体的代码操作了:
在AppDelegate类的-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法中奖数据存储到数据库:
//将设置上面对象属性的方法封装起来
在BookTableViewController.m文件中:
//导入头文件,实现协议和定义属性
//NSFetchedResultsController从数据库抓取数据
#pragmamark-Tableviewdatasource//显示表格内容
//组数
//行数
//将设置行内容的方法封装,调用它设置cell内容
//设置单元格的编辑与否
//只进行删除数据
//删除数据时,同时新插入插入数据
//删除数据时,修改数据并显示
#pragmamark-<NSFetchedResultsControllerDelegate>代理方法,更新变化后的表格信息
演示结果如下:
没有进行任何操作时: 选中单元格往左滑动,删除数据时
删除数据时,同时新插入两个对象 没删除一次,对象的属性价格就发生了改变
要求:创建一个实体对象Book数据库表,多次设置它的属性,并将它显示在表格中,显示后进行的操作有:(1)仅仅进行删除对象、(2)在删除时同时又插入两条对象信息、(3)删除时修改它的属性并再从新显示该对象
前期的创建数据库表的具体步骤:
1、创建新项目时,勾选UseCoreData,生成CoreData____NSFetchResultController.xcdatamodel文件,此时AppDelegate类中自动封装了sqlite的大量方法和需要的managedObjectContext、managedObjectModel、persistentStoreCoordinator三个对象等;
2、点击该文件,进入设置面板,点击左下角的AddEntity,创建实体对象并设置它的类名,同时在Attribute处添加该实体对象的属性;
3、选中该实体对象,点击模拟器菜单栏的Editor下的createNSManagedObjectSubclass..,自动生成实体对象的类Book.h和Book.m文件,类中自动生成了实体对象的所有属性;
4、再一次进入设置面板,点击右下角的style,可以查看成功创建的数据库表。
5、进入故事板Storyboard中,删除viewController控制器和它的类,重新拖入一个新的视图控制器和一个表格视图TableView;
6、新建一个新的类为BookTableViewController继承自UITableViewController,并将上面新拖入的视图控制器关联这个类即可。好了,前期工作完成。
接下来即时具体的代码操作了:
在AppDelegate类的-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法中奖数据存储到数据库:
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{ //读取偏好设置,使测试数据只插入一次 NSUserDefaults*userDefaults=[NSUserDefaultsstandardUserDefaults]; self.isInserted=[userDefaultsboolForKey:@"isInserted"]; if(!self.isInserted) { [selfaddBookWithTitle:@"《红楼梦》"andPrice:@50.5]; [selfaddBookWithTitle:@"《西游记》"andPrice:@48.5]; [selfaddBookWithTitle:@"《水浒传》"andPrice:@67.5]; [selfaddBookWithTitle:@"《三国演义》"andPrice:@70.0]; [selfaddBookWithTitle:@"《资治通鉴》"andPrice:@79.0]; [selfaddBookWithTitle:@"《本草纲目》"andPrice:@59.0]; [selfaddBookWithTitle:@"《二十四史》"andPrice:@98.0]; } //设置偏好设置 [userDefaultssetBool:YESforKey:@"isInserted"]; [userDefaultssynchronize]; returnYES; }
//将设置上面对象属性的方法封装起来
-(void)addBookWithTitle:(NSString*)titleandPrice:(NSNumber*)price { //取出实体对象 Book*book=[NSEntityDescriptioninsertNewObjectForEntityForName:NSStringFromClass([Bookclass])inManagedObjectContext:self.managedObjectContext]; //设置属性 book.title=title; book.price=price; //保存数据到持久层 [selfsaveContext]; }
在BookTableViewController.m文件中:
//导入头文件,实现协议和定义属性
#import"BookTableViewController.h" #import"AppDelegate.h" #import"Book.h" @interfaceBookTableViewController()<NSFetchedResultsControllerDelegate> @property(strong,nonatomic)NSFetchedResultsController*fetchResultVC; @property(strong,nonatomic)NSManagedObjectContext*managedObjectContext;
//NSFetchedResultsController从数据库抓取数据
-(void)viewDidLoad{ [superviewDidLoad]; //创建应用程序对象 AppDelegate*appDelegate=[[UIApplicationsharedApplication]delegate]; self.managedObjectContext=appDelegate.managedObjectContext; //fetchResultVC获取CoreData中的数据 NSError*error=nil; [self.fetchResultVCperformFetch:&error]; if(error) { NSLog(@"获取数据失败"); } }
//懒加载创建NSFecthedResultsController控制器对象
-(NSFetchedResultsController*)fetchResultVC { if(!_fetchResultVC) { //创建请求对象 NSFetchRequest*fetchRequest=[NSFetchRequestfetchRequestWithEntityName:NSStringFromClass([Bookclass])]; //批处理,每次从数据库中抓取的数量 fetchRequest.fetchBatchSize=10; //设置排序对象 NSSortDescriptor*priceSort=[NSSortDescriptorsortDescriptorWithKey:@"price"ascending:YES]; [fetchRequestsetSortDescriptors:@[priceSort]]; //创建fetchResultVC _fetchResultVC=[[NSFetchedResultsControlleralloc]initWithFetchRequest:fetchRequestmanagedObjectContext:self.managedObjectContextsectionNameKeyPath:nilcacheName:@"book"]; //设置fetchResultVC的代理 _fetchResultVC.delegate=self; } return_fetchResultVC; }
#pragmamark-Tableviewdatasource//显示表格内容
//组数
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView { returnself.fetchResultVC.sections.count; }
//行数
-(NSInteger)tableView:(UITableView*)tableViewnumberOfRowsInSection:(NSInteger)section { id<NSFetchedResultsSectionInfo>sectionInfo=[self.fetchResultVC.sectionsobjectAtIndex:section]; return[sectionInfonumberOfObjects]; }
//将设置行内容的方法封装,调用它设置cell内容
-(void)configCell:(UITableViewCell*)cellindexPath:(NSIndexPath*)indexPath { Book*book=[self.fetchResultVCobjectAtIndexPath:indexPath]; cell.textLabel.text=book.title; cell.detailTextLabel.text=[NSStringstringWithFormat:@"$%@",book.price]; }
-(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath { //1.根据reuseIdentifier,先到对象池中去找重用的单元格对象 staticNSString*reuseIdentifier=@"bookCell"; UITableViewCell*cell=[self.tableViewdequeueReusableCellWithIdentifier:reuseIdentifier]; //2.如果没有找到,自己创建单元格对象 if(cell==nil) { cell=[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:reuseIdentifier]; } //3.设置单元格对象的内容 [selfconfigCell:cellindexPath:indexPath]; returncell; }
//设置单元格的编辑与否
-(BOOL)tableView:(UITableView*)tableViewcanEditRowAtIndexPath:(NSIndexPath*)indexPath { returnYES; }
//只进行删除数据
Book*book=[self.fetchResultVCobjectAtIndexPath:indexPath];//获取实体对象 NSError*error=nil; //删除数据 //从CoreData数据库删除数据 [self.managedObjectContextdeleteObject:book];//从上下文是删除该实体对象 [self.managedObjectContextsave:&error];//保存上下文
//删除数据时,同时新插入插入数据
AppDelegate*appDelegate=[[UIApplicationsharedApplication]delegate]; [appDelegateaddBookWithTitle:@"《狂人日记》"andPrice:@20.0]; [appDelegateaddBookWithTitle:@"《洗冤集录》"andPrice:@24.5];
//删除数据时,修改数据并显示
//在删除数据时,修改它的数据并更新 book.price=@([book.pricedoubleValue]+10); [self.managedObjectContextsave:&error]; if(error) { NSLog(@"删除失败"); }
#pragmamark-<NSFetchedResultsControllerDelegate>代理方法,更新变化后的表格信息
//表格开始更新 -(void)controllerWillChangeContent:(NSFetchedResultsController*)controller { [self.tableViewbeginUpdates]; } //尽心更新处理 -(void)controller:(NSFetchedResultsController*)controllerdidChangeObject:(id)anObjectatIndexPath:(NSIndexPath*)indexPathforChangeType:(NSFetchedResultsChangeType)typenewIndexPath:(NSIndexPath*)newIndexPath { if(type==NSFetchedResultsChangeDelete)//删除数据 { [self.tableViewdeleteRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic]; } elseif(type==NSFetchedResultsChangeInsert)//插入数据 { [self.tableViewinsertRowsAtIndexPaths:@[newIndexPath]withRowAnimation:UITableViewRowAnimationAutomatic]; } elseif(type==NSFetchedResultsChangeUpdate)//更新(修改)数据 { UITableViewCell*cell=[self.tableViewcellForRowAtIndexPath:indexPath]; [selfconfigCell:cellindexPath:indexPath]; [self.tableViewreloadRowsAtIndexPaths:@[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic]; } } //表格更新结束 -(void)controllerDidChangeContent:(NSFetchedResultsController*)controller { [self.tableViewendUpdates]; }
演示结果如下:
没有进行任何操作时: 选中单元格往左滑动,删除数据时
删除数据时,同时新插入两个对象 没删除一次,对象的属性价格就发生了改变
相关文章推荐
- 当UITextField被系统键盘挡住的时候如何解决
- 【UIKit-124-4】#import <UIKit/UIView.h>
- 优化UITableViewCell高度计算的那些事
- UIView动画
- Number Sequence
- request.getInputStream中文乱码解决方案
- iOS UITextView 光标问题
- IOS UILabel
- 【转】有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?
- 自定义UITableViewCell 上的多个按钮点击事件处理
- UICollectionView基础
- quick减少包体
- 传感器 -UIAccelerometer
- iOS-Core-Animation-Advanced-Techniques(六)
- 数莓派kernel building官方文档
- /res/values 目录详解
- DRUID连接池的使用——为监控而生的DB池[转]
- CYC-非常炫酷的UIView动画-02
- NGUI控件
- UI 框架、ORM、权限系统