例1:
用好NSFetchedResultsController,程序的performance能大 大提高。原因在于你用NSFetchedResultsController去读取数据的话,苹果公司那些顶尖的工程师已经帮你想好了如何最大效率地读取 数据库。 所以,干脆利落地去掉NSArray和NSMutableArray,只用NSFetchedResultsController! 1,首先在h文件加入下面这段代码。
@interfaceFailedBanksListViewController:UITableViewController{ NSFetchedResultsController*_fetchedResultsController; NSManagedObjectContext*_context; } @property(nonatomic, retain) NSFetchedResultsController*fetchedResultsController; @property(nonatomic, retain)NSManagedObjectContext*context; @end2,在m文件中,加入下面的代码
@synthesize fetchedResultsController = _fetchedResultsController;3,在dealloc函数中,加入下面的代码:
self.fetchedResultsController.delegate=nil; self.fetchedResultsController =nil;4,在viewDidUnload函数中,加入下面的代码:
-(void)viewDidUnload { self.fetchedResultsController =nil; }5,在m文件中,加入如下函数(以FailedBackInfo为数据对象)
-(NSFetchedResultsController*)fetchedResultsController { if(_fetchedResultsController !=nil){ return _fetchedResultsController; NSFetchRequest*fetchRequest =[[NSFetchRequest alloc] init]; NSEntityDescription*entity =[NSEntityDescription entityForName:@"FailedBankInfo" inManagedObjectContext:_context]; [fetchRequest setEntity:entity]; NSSortDescriptor*sort =[[NSSortDescriptor alloc] initWithKey:@"details.closeDate" ascending:NO]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]]; [fetchRequest setFetchBatchSize:20]; NSFetchedResultsController*theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_context sectionNameKeyPath:nil cacheName:@"Root"]; self.fetchedResultsController = theFetchedResultsController; _fetchedResultsController.delegate=self; [sort release]; [fetchRequest release]; [theFetchedResultsController release]; return _fetchedResultsController; }上面的代码中,entity为实体对象,_context是coredata的NSManagedObject对象,它是连接数据库的一个上下文对象,相当于一个连接器。sort用来排序。cacheName用来组织数据成sections(这样组织方便后面展示) 6,在viewDidLoad中加入下面代码:
-(void)viewDidLoad { [super viewDidLoad]; NSError*error; if(![[self fetchedResultsController] performFetch:&error]){ // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error,[error userInfo]); exit(-1);// Fail } self.title =@"Failed Banks"; }7,接下来,在UITableView中显示。
-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section { id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section]; return[sectionInfo numberOfObjects]; } -(void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath { FailedBankInfo*info =[_fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = info.name; cell.detailTextLabel.text =[NSString stringWithFormat:@"%@, %@", info.city, info.state]; } -(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath { staticNSString*CellIdentifier=@"Cell"; UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if(cell ==nil){ cell =[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; } // Set up the cell... [self configureCell:cell atIndexPath:indexPath]; return cell; }8,当数据发生变化时,coredata会自动通知显示层即UITableView作刷新。
-(void)controllerWillChangeContent:(NSFetchedResultsController*)controller { // The fetch controller is about to start sending change notifications, so prepare the table view for updates. [self.tableView beginUpdates]; }
-(void)controller:(NSFetchedResultsController*)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath { UITableView*tableView =self.tableView; switch(type){ case NSFetchedResultsChangeInsert: [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeUpdate: [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; case NSFetchedResultsChangeMove: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; // Reloading the section inserts a new row and ensures that titles are updated appropriately. [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade]; break; } }
-(void)controller:(NSFetchedResultsController*)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { switch(type){ case NSFetchedResultsChangeInsert: [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; break; } }
-(void)controllerDidChangeContent:(NSFetchedResultsController*)controller { // The fetch controller has sent all current change notifications, so tell the table view to process all updates. [self.tableView endUpdates]; }
例2:
在CoreData为UITableView提供数据的时候,使用NSFetchedReslutsController能提高体验,因为用NSFetchedReslutsController去读数据的话,能最大效率的读取数据库,也方便数据变化后更新界面,
具体使用方法如下:
1.添加属性
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@synthesize fetchedResultsController = _fetchedResultsController;
2. 重载- (NSFetchedResultsController *)fetchedResultsController初始化NSFetchedResultsController
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
self.fetchedResultsController = [[CoreDataManager getInstance] contactFetchedResultsController];
self.fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
其中
- (NSFetchedResultsController *)contactFetchedResultsController {
BSHLOG(@"contactFetchedResultsController");
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
NSEntityDescription *entity = [NSEntityDescription entityForName:kCoreDataEntityContacts
inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSSortDescriptor *recordsort = [NSSortDescriptor sortDescriptorWithKey:@"name"
ascending:NO];
[request setSortDescriptors:[NSArray arrayWithObjects:recordsort, nil]];
NSFetchedResultsController *controller = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
cacheName:nil];
return [controller autorelease];
}
注意:初始化NSFetchedResultsController 的时候,NSFetchRequest必须设置NSSortDescriptor
3. 在viewDidLoad中为NSFetchedResultsController获取值
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.titleNavigationItem.title = NSLocalizedString(@"contacts_title", nil);
[self fetchContacts];
}
- (void)fetchContacts {
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
// Update to handle the error appropriately.
BSHLOG(@"[fetchSinaFriend] Unresolved error %@, %@", error, [error userInfo]);
//exit(-1); // Fail
}
}
4.在viewDidUnload和dealloc中释放
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[self releaseUI];
}
- (void)dealloc {
[self releaseUI];
[super dealloc];
}
- (void)releaseUI {
self.tableView = nil;
self.titleNavigationItem = nil;
self.fetchedResultsController.delegate = nil;
self.fetchedResultsController = nil;
}
5.显示在UITableView中
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
int count = [sectionInfo numberOfObjects];
BSHLOG(@"numberOfRowsInSection count = %d", count);
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *reuseIdentifier = @"ContactsViewController";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:reuseIdentifier];
}
EntityContacts *contact = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = contact.name;
return cell;
}
6.添加NSFetchedResultsControllerDelegate的方法,当数据发生变化时,自动刷新UITableView
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[_tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath {
switch(type) {
case NSFetchedResultsChangeInsert:{
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;
case NSFetchedResultsChangeDelete:
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
break;
case NSFetchedResultsChangeUpdate:
[_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationBottom];
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationTop];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[_tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeDelete:
[_tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationBottom];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[_tableView endUpdates];
}