当前位置: 代码迷 >> 综合 >> iOS NSFetchedResultsController的使用(使用数据库时提高效率)
  详细解决方案

iOS NSFetchedResultsController的使用(使用数据库时提高效率)

热度:20   发布时间:2024-01-20 19:09:10.0

例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;
@end
2,在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 =[NSEntityDescriptionentityForName:@"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:UITableViewCellStyleSubtitlereuseIdentifier: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];

}

  相关解决方案