核心数据:严重的应用错误

aka*_*kyy 4 iphone core-data nsfetchedresultscontroller nsmanagedobjectcontext

我正在完成我的核心数据应用程序和我开始我的最终测试.

Everyfing工作正常,除了一件事,随机发生,我无法重现它.

这是日志(使用NSZombieEnabled):

2011-07-03 20:27:53.144 MYAPP[1882:707] -[__NSCFType controllerWillChangeContent:]: unrecognized selector sent to instance 0x4a4c490
2011-07-03 20:27:53.149 MYAPP[1882:707] Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  -[__NSCFType controllerWillChangeContent:]: unrecognized selector sent to instance 0x4a4c490 with userInfo (null)
2011-07-03 20:27:53.165 MYAPP[1882:707] CoreAnimation: ignoring exception: -[__NSCFType controllerWillChangeContent:]: unrecognized selector sent to instance 0x4a4c490
Run Code Online (Sandbox Code Playgroud)

它在这里崩溃:

NSManagedObjectContext *context = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; // IT'S OK
NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:@"Kontrahent" inManagedObjectContext:context]; // IT'S OK
for(NSString *key in kontrahent) [newManagedObject setValue:[kontrahent valueForKey:key] forKey:key];  // IT'S OK
NSError *error = nil;
if (![context save:&error]) {  // IT'S NOT OK
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}
Run Code Online (Sandbox Code Playgroud)

我的行动层次:

1. Open application
2. Open my 'root' list (with NSFetchedResultsController, entity: "Faktura")
3. Tap 'Add' button
4. In my 'Add' view controller I create another object (entity: "Kontrahent")
5. I try to add it to database
6. It crashes / It doesn't.

SCHEME:

        +---[moc save:]---> Faktury (my root class)
        |                        ?
        +-----delegate-- FakturaCreator <---[moc save:]--+  <--- HERE IT CRASHES
                                 ?                       |
                         KontrahentCreator ---delegate---+
Run Code Online (Sandbox Code Playgroud)

我知道它与NSFetchedResultsController和有关[moc save:].但我无法找到我的问题,因为它在需要时会崩溃.有时它有效,有时会崩溃.如果你知道这个问题,请帮助我:)


如果您需要更多代码......

NSFetchedResultsController的东西 (Faktury.m)

#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController {

    if (__fetchedResultsController != nil) return __fetchedResultsController;

    // Setup the table

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Faktura" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Setup the sort descriptors

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"NumerFV" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    // Create the fetched results controller

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {

        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"B??d Krytyczny" message:@"Wyst?pi? nieznany b??d przy zmienianiu zawarto?ci w bazie danych. Dla dobra twoich danych prosimy niezw?ocznie wyj?? z aplikacji i spróbowa? ponownie." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __fetchedResultsController;
}    

#pragma mark - Fetched results controller delegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [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([[[controller sections] objectAtIndex:0] numberOfObjects] == 0) {
        emptySectionView.hidden = NO;
        UIBarButtonItem *editBtn = [[UIBarButtonItem alloc] initWithTitle:@"Edytuj" style:UIBarButtonItemStyleBordered target:self action:@selector(toogleEditing)];
        editBtn.enabled = NO;
        [self.navigationItem setLeftBarButtonItem:editBtn animated:NO];
        [editBtn release];
    } else {
        emptySectionView.hidden = YES;
        self.navigationItem.leftBarButtonItem.enabled = YES;
    }

    UITableView *table = tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [table insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [table deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:(KSTableViewCell *)[table cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

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

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [tableView endUpdates];
}
Run Code Online (Sandbox Code Playgroud)

当我点按"添加"按钮时 (Faktury.m)

- (void)add:(id)sender {
    FakturaCreator *form = [[FakturaCreator alloc] init];
    form.hidesBottomBarWhenPushed = YES;
    form.delegate = self;
    form.managedObjectContext = self.managedObjectContext;
    [self.navigationController pushViewController:form animated:YES];
    [form release];
}
Run Code Online (Sandbox Code Playgroud)

aka*_*kyy 6

好的,我找到了我的问题.我有一个'KontrahentPicker',它也有NSFetchedResultsController.但这UIViewController被呈现为modalViewController.我把我的Kontrahent模态解散并释放了.但是NSFRC代表仍然活跃.

我把它解决了我的问题

self.fetchedResultsController.delegate = nil;
Run Code Online (Sandbox Code Playgroud)

-dealloc方法中.