CoreData-Fehler driving me crazy... CoreData: Schwere Anwendungsfehler. Eine Ausnahme abgefangen, die aus Delegierten der NSFetchedResultsController

Meine Anwendung hat zwei Reiter bars... Jeder der Benutzer zu einem tableviewcontroller, präsentiert ihn mit einer Liste von Elementen. Der erste Blick lässt den Benutzer-Datensatz Einträge in der Datenbank. Die anderen Reiter/view aus der Datenbank liest und präsentiert diese Elemente für den Nutzer jedoch keine updates gemacht werden, um die coreData/persistent speichern aus dieser zweiten Ansicht.

Wenn ich ein neues Element hinzufügen, über den ersten viewcontroller, es zeigt sich perfekt im Blick. Jedoch, sobald ich Tippen Sie auf die Registerkarte andere bar zu sehen, die neuen Artikel erscheinen, die viewcontroller, bekomme ich die Fehlermeldung, die unten aufgeführt werden, und das neu hinzugefügte Element nicht angezeigt wird... Hinweis: wenn ich beenden der app, und laden/starten Sie es erneut, und starten Sie durch Tippen auf das 2. tab-bar, das neue Element zeigt sich sehr gut, so dass ich weiß, wird das Modell aktualisiert in Ordnung.

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1046
2011-10-20 20:56:15.117 Gtrac[72773:fb03] CoreData: error: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (4) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out). with userInfo (null)

Code von der Stellvertretung Anwendung, in denen der managedObjectContext an die zwei viewControllers.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {


    //get a point to the master database context
    NSManagedObjectContext *context = [self managedObjectContext];
    if (!context) {
        //Handle the error.
    }

    //create tab bar controller and array to hold each of the tab-based view controllers that will appear as icons at bottom of screen
    tabBarController = [[UITabBarController alloc] init];
    NSMutableArray *localControllersArray = [[NSMutableArray alloc] initWithCapacity:5];    


    //
    //setup first tab bar item
    //
    //
    //alloc the main view controller - the one that will be the first one shown in the navigation control
    RootViewController *rootViewController = [[RootViewController alloc] initWithTabBar];

    //Pass the managed object context to the view controller.
    rootViewController.managedObjectContext = context;

    //create the navigation control and stuff the rootcontroller inside it
    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

    //set the master navigation control 
    self.navigationController = aNavigationController;

    //add the navigaton controller as the first tab for the tab bar
    [localControllersArray addObject:aNavigationController];

    [rootViewController release];
    [aNavigationController release];    


    //
    //setup the other tab bar
    //
    //

    //alloc the view controller 
    vcSimulator *vcSimulatorController = [[vcSimulator alloc] initWithTabBar];

    UINavigationController *blocalNavigationController = [[UINavigationController alloc] initWithRootViewController:vcSimulatorController];

    //Pass the managed object context to the view controller.
    vcSimulatorController.managedObjectContext = context;

    //add this controller to the array of controllers we are building
    [localControllersArray addObject:blocalNavigationController];

    //release these guys, they are safely stored in the array - kill these extra references
    [blocalNavigationController release];
    [vcSimulatorController release];


    //
    //
    //ok, all the tab bars are in the array - get crackin
    //
    //
    //load up our tab bar controller with the view controllers
    tabBarController.viewControllers = localControllersArray;

    //release the array because the tab bar controller now has it
    [localControllersArray release];

    [window addSubview:[tabBarController view]];
    [window makeKeyAndVisible];

    return YES;




When I add a new item via the first viewcontroller, it shows up perfectly in the view.  However, as soon as I tap on the other tab bar to see the new item appear in that viewcontroller, I get the error listed above, and the newly added item does not appear...   Note: if I stop the app and reload/re-run it, and start by tapping the 2nd tabbar, the new item shows up fine, so I know the model is being updated fine.

Here are the tableview delegate methods from the 2nd view controller.



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

    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    
    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];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;
    }

}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    

    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 {
    [self.tableView endUpdates];

}

Jede Hilfe, die Sie bereitstellen können, wäre sehr dankbar.

Suchte ich diese Seite und fand viele Instanzen von diesem Fehler, aber keiner scheint zu passen. Ich habe auch gesehen, wie Referenzen abzuleiten, dass dieser Fehler den ich sehe ist tatsächlich ein bekannter bug in der Apple-code...

* AKTUALISIERT INFORMATIONEN *

Bin ich wieder zurück und legen Sie Haltepunkte in den code, und bin der Bearbeitung der ursprünglichen Frage mit diesen zusätzlichen Informationen. Wenn der Benutzer fügt einen neuen Eintrag in die Datenbank ist er übergang von der rootview des listCourses anzeigen. Das hinzufügen Transaktion funktioniert einwandfrei und die listCourses Ansicht UITableView aktualisiert wird perfekt.

Wenn ich auf die andere Ansicht, dass auch liest Daten aus der gleichen Kern-Daten-Modell, es ist viewcontroller läuft durch die folgende Sequenz aber nie endet, das neue Element zu der tableview. Hier ist die Reihenfolge durchläuft.

Simulator VC:

- controllerWillChangeContent which runs...
        [self.tableView beginUpdates];

    - didChangeObject 
        ..with message: NSFetchedResultsChangeUpdate
        ..which ran:
        [self configureCell:[tableView cellForRowAtIndexPath:indexPath] 

    - controllerDidChangeContent:   
        [self.tableView endUpdates];

Den anderen viewcontroller, das funktioniert Super, geht durch diese Sequenz sofort nach dem Eintrag wird der Datenbank Hinzugefügt.

ListCourses VC:

- didChangeSection
    ...with message:  NSFetchedResultsChangeInsert
...which ran:
    [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

- didChangeObject
    ..with message: NSFetchedResultsChangeInsert
    ..which ran:
    [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

Warum hat der einen viewcontroller Holen Sie sich die NSFetchedResultsChangeInsert Nachricht, aber die andere nicht?

Hier sind die delegate-Methoden des fehlerhaften viewcontroller.

//Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        //Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}





- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    //The fetch controller is about to start sending change notifications, so prepare the table view for updates.
    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    

    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    


    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:

            //[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] 
                    atIndexPath:indexPath];
            //[tableView reloadData];


            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 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;
    }
    NSLog(@"vc>>>  about to reload data");
    // [self.tableView reloadData];

}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
    //[self.tableView reloadData];

}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    //The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    NSLog(@">>> Entering %s [Line %d] ", __PRETTY_FUNCTION__, __LINE__);    
    [self.tableView endUpdates];

}

Dank,
phil

InformationsquelleAutor phil | 2011-10-21
Schreibe einen Kommentar