2013-07-04 18 views
1

我正在使用HTTP GET方法從網絡中提取數據。然後,我從Web上獲取JSON數據並將其保存到CoreData中。我有一個UITableView與自定義UITableViewCells更新與NSFetchedResultsController。在使用NSFetchedResultsController更新UITableView時將數據從Web保存到Core Data中

但是,當我去保存數據時,tableView將只更新已經在屏幕上的內容,當我向下滾動時,tableView變成白色。

在日誌中有一些我收到一些錯誤:

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. attempt to delete and reload the same index path ({length = 2, path = 0 - 43}) with userInfo (null)

這裏是我的代碼,該NSFetchedResultsControllerDelegate使用在didChangeObject方法:

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.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
     break; 

    case NSFetchedResultsChangeMove: 
     [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
         withRowAnimation:UITableViewRowAnimationFade]; 
     break; 
} 

什麼,我可以做任何想法?

謝謝!

回答

0

那麼你呢?

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 

你可以把我的,它應該肯定工作,我用它在幾個項目。 只要讓你的tableViewController繼承這一個。 然後初始化和你fetchedResultsController傳遞到您的tableViewController,並呼籲有:

[self setupFetchedResultsController:yourFetchResultsController]; 

SMCoreDataTableViewController.m:

#import "SMCoreDataTableViewController.h" 

@interface SMCoreDataTableViewController() 
@property (nonatomic) BOOL beganUpdates; 
@end 

@implementation SMCoreDataTableViewController 

- (void)performFetch 
{ 
    if (self.fetchedResultsController) { 
     if (self.fetchedResultsController.fetchRequest.predicate) { 
      if (self.debug) NSLog(@"[%@ %@] fetching %@ with predicate: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName, self.fetchedResultsController.fetchRequest.predicate); 
     } else { 
      if (self.debug) NSLog(@"[%@ %@] fetching all %@ (i.e., no predicate)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), self.fetchedResultsController.fetchRequest.entityName); 
     } 
     NSError *error; 
     [self.fetchedResultsController performFetch:&error]; 
     if (error) NSLog(@"[%@ %@] %@ (%@)", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [error localizedDescription], [error localizedFailureReason]); 
    } else { 
     if (self.debug) NSLog(@"[%@ %@] no NSFetchedResultsController (yet?)", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); 
    } 
    [self.tableView reloadData]; 
} 

- (void)setupFetchedResultsController:(NSFetchedResultsController *)newfrc 
{ 
    NSFetchedResultsController *oldfrc = _fetchedResultsController; 
    if (newfrc != oldfrc) { 
     _fetchedResultsController = newfrc; 
     newfrc.delegate = self; 
     if ((!self.title || [self.title isEqualToString:oldfrc.fetchRequest.entity.name]) && (!self.navigationController || !self.navigationItem.title)) { 
      self.title = newfrc.fetchRequest.entity.name; 
     } 
     if (newfrc) { 
      if (self.debug) NSLog(@"[%@ %@] %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), oldfrc ? @"updated" : @"set"); 
      [self performFetch]; 
     } else { 
      if (self.debug) NSLog(@"[%@ %@] reset to nil", NSStringFromClass([self class]), NSStringFromSelector(_cmd)); 
      [self.tableView reloadData]; 
     } 
    } 
} 

#pragma mark - UITableViewDataSource 

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects]; 
} 

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{ 
    return [[[self.fetchedResultsController sections] objectAtIndex:section] name]; 
} 

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index 
{ 
    return [self.fetchedResultsController sectionForSectionIndexTitle:title atIndex:index]; 
} 

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView 
{ 
    return [self.fetchedResultsController sectionIndexTitles]; 
} 

#pragma mark - NSFetchedResultsControllerDelegate 

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
{ 
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) { 
     [self.tableView beginUpdates]; 
     self.beganUpdates = YES; 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller 
    didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex 
    forChangeType:(NSFetchedResultsChangeType)type 
{ 
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) 
    { 
     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)controller:(NSFetchedResultsController *)controller 
    didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath 
{ 
    if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext) 
    { 
     switch(type) 
     { 
      case NSFetchedResultsChangeInsert: 
       [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

      case NSFetchedResultsChangeDelete: 
       [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

      case NSFetchedResultsChangeUpdate: 
       [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 

      case NSFetchedResultsChangeMove: 
       [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
       break; 
     } 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller 
{ 
    if (self.beganUpdates) [self.tableView endUpdates]; 
} 

- (void)endSuspensionOfUpdatesDueToContextChanges 
{ 
    _suspendAutomaticTrackingOfChangesInManagedObjectContext = NO; 
} 

- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend 
{ 
    if (suspend) { 
     _suspendAutomaticTrackingOfChangesInManagedObjectContext = YES; 
    } else { 
     [self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0]; 
    } 
} 

@end 

SMCoreDataTableViewController.h:

#import <UIKit/UIKit.h> 
#import <CoreData/CoreData.h> 

@interface SMCoreDataTableViewController : UITableViewController <NSFetchedResultsControllerDelegate> 

@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController; 

@property (nonatomic) BOOL suspendAutomaticTrackingOfChangesInManagedObjectContext; 
@property BOOL debug; 

- (void)setupFetchedResultsController:(NSFetchedResultsController *)fetchedResultsController; 

@end 
相關問題