有人尝试过“更多 iOS 6 开发”中的 SuperDB 应用程序吗?单击“+”按钮时出现此错误。我完全按照书中的内容进行操作,但我无法弄清楚哪里出了问题。我在 xcode 5 中运行该应用程序。请告知。
SuperDB[1676:a0b] CoreData:错误:严重的应用程序错误。在调用 -controllerDidChangeContent: 期间,从 NSFetchedResultsController 的委托中捕获了一个异常。尝试将第 0 行插入第 0 节,但使用 userInfo (null) 更新后第 0 节中只有 0 行
#import "HeroListController.h"
#import "AppDelegate.h"
@interface HeroListController ()
@property (nonatomic, strong, readonly) NSFetchedResultsController *fetchedResultsController;
@end
@implementation HeroListController
@synthesize fetchedResultsController=_fetchedResultsController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
// Select the Tab Bar button
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSInteger selectedTab = [defaults integerForKey:kSelectedTabDefaultsKey];
UITabBarItem *item = [self.heroTabBar.items objectAtIndex:selectedTab];
[self.heroTabBar setSelectedItem:item];
// Fetch any existing entities
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
UIAlertView *alert =
[[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Error loading data",
@"Error loading data")
message:[NSString stringWithFormat:NSLocalizedString(@"Error was: %@, quitting.",
@"Error was: %@, quitting."),
[error localizedDescription]]
delegate:self
cancelButtonTitle:NSLocalizedString(@"Aw, Nuts", @"Aw, Nuts")
otherButtonTitles:nil];
[alert show];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[self.fetchedResultsController sections] objectAtIndex:section] numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=@"HeroListCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSManagedObject *aHero = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSInteger tab = [self.heroTabBar.items indexOfObject:self.heroTabBar.selectedItem];
switch (tab) {
case kByName:
cell.textLabel.text = [aHero valueForKey:@"name"];
cell.detailTextLabel.text = [aHero valueForKey:@"secretIdentity"];
break;
case kBySecretIdentity:
cell.textLabel.text = [aHero valueForKey:@"secretIdentity"];
cell.detailTextLabel.text = [aHero valueForKey:@"name"];
break;
}
return cell;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSManagedObjectContext *managedObjectContext=[self.fetchedResultsController
managedObjectContext];
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[managedObjectContext deleteObject:[self.fetchedResultsController
objectAtIndexPath:indexPath]];
NSError *error;
if (![managedObjectContext save:&error]) {
UIAlertView *alert= [[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Error saving entity",
@"Error saving entity")
message:
[NSString stringWithFormat:NSLocalizedString(@"Error was: %@, quitting.",
@"Error was: %@, quitting."), [error localizedDescription]]
delegate:self
cancelButtonTitle:NSLocalizedString(@"Aw, Nuts", @"Aw, Nuts")
otherButtonTitles:nil];
[alert show];
}
}
}
#pragma mark - UITabBarDelegate Methods
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSUInteger tabIndex=[tabBar.items indexOfObject:item];
[defaults setInteger:tabIndex forKey:kSelectedTabDefaultsKey];
[NSFetchedResultsController deleteCacheWithName:@"Hero"];
_fetchedResultsController.delegate = nil;
_fetchedResultsController = nil;
NSError *error;
if (![self.fetchedResultsController performFetch:&error]) {
NSLog(@"Error performing fetch: %@", [error localizedDescription]);
}
[self.heroTableView reloadData];
}
#pragma mark - FetchedResultsController Property
- (NSFetchedResultsController *)fetchedResultsController
{
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *managedObjectContext = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Hero"
inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSUInteger tabIndex = [self.heroTabBar.items indexOfObject:self.heroTabBar.selectedItem];
if (tabIndex == NSNotFound) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
tabIndex = [defaults integerForKey:kSelectedTabDefaultsKey];
}
NSString *sectionKey = nil;
switch (tabIndex) {
// Notice that the kByName and kBySecretIdentity Code are nearly identical.
// A refactoring opportunity?
case kByName: {
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"secretIdentity"
ascending:YES];
NSArray *sortDescriptors =
[[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
sectionKey = @"name";
break;
}
case kBySecretIdentity:{
NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"secretIdentity"
ascending:YES];
NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES];
NSArray *sortDescriptors =
[[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
sectionKey = @"secretIdentity";
break;
}
}
_fetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext sectionNameKeyPath:sectionKey
cacheName:@"Hero"];
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
#pragma mark - NSFetchedResultsControllerDelegate Methods
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.heroTableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.heroTableView endUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id < NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.heroTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.heroTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
switch(type) {
case NSFetchedResultsChangeInsert:
[self.heroTableView insertRowsAtIndexPaths:@[newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.heroTableView deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
case NSFetchedResultsChangeMove:
break;
}
}
#pragma mark - UIAlertViewDelegate Methods
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex{
exit(-1);
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
self.addButton.enabled = !editing;
[self.heroTableView setEditing:editing animated:animated];
}
- (IBAction)addHero:(id)sender {
NSManagedObjectContext *managedObjectContext= [self.fetchedResultsController managedObjectContext];
NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
[NSEntityDescription insertNewObjectForEntityForName:[entity name]
inManagedObjectContext:managedObjectContext];
NSError *error = nil;
if (![managedObjectContext save:&error]) {
UIAlertView *alert =
[[UIAlertView alloc]
initWithTitle:NSLocalizedString(@"Error saving entity",
@"Error saving entity")
message:[NSString stringWithFormat:NSLocalizedString(@"Error was: %@, quitting.", @"Error was: %@, quitting."),
[error localizedDescription]]
delegate:self
cancelButtonTitle:NSLocalizedString(@"Aw, Nuts", @"Aw, Nuts")
otherButtonTitles:nil];
[alert show];
}
}
@end