What should I watch to debug this Core-Data / NSFetchedResultsController bug?

I've got a bug in my Core Data implementation that I cannot seem to get a hold of, and I need some tips on where I should be looking to figure out how to fix it.

To make a long story short, I have a UITableView being populated by a NSFetchedResultsController. I want my users to be able to change the sorting options for the data, so I give them a picker that will change the underlying fetchedResultsController to different preset configurations. I can change back and forth between the different fetchedResultsControllers with no issue whatsoever. I can add and remove data, never experiencing any crashes, no problem. However, on 2 (out of 6, and always the same 2) of the fetchedResultController configurations, items added to the database are not added to the tableview. And items that are in the tableview disappear once edited.

Here are the steps I go through to reproduce the bug:

  1. Set the sorting to a configuration that works
  2. Add a new item to the database (at this point controllerWillChangeContent fires)
  3. Change to a configuration that doesn't work
  4. Add a new item to the database (controllerWillChangeContent does not fire)
  5. Switch back to the working configuration
  6. The item added is now visible in the tableView
  7. Switch back to the non-working configuration
  8. The item is now visible in the tableView
  9. Edit the item (controllerWillChangeContent is fired, but controller:DidChangeObject: is fired with the type as NSFetchedResultsChangeDelete instead of NSFetchedResultsChangeUpdate)
  10. Change back to the working configuration, and the item is changed and visible again.

I'm at my wits end with this thing. I'm completely out of ideas. There is literally no difference between the way these 2 fetchedResultsControllers are created and the 4 others. Any help that can be offered will be greatly appreciated.

--EDIT--

Still having some issues with this. To reiterate some of the answers to TechZen's questions:

  • None of my attributes are set as transient values
  • I'm using a flat model at the moment. It's a single entity with direct attributes. There are no relationships.
  • The problem persists with the caches set to nil
  • I am setting the old frc's delegate to nil before every change, and setting the new frc's delegate to self at the end of the switch. This is consistant across all 6 frcs
  • I am releasing the old frc and creating a new one each time the user switches to a different sort option.

For those interested, the code I'm using to switch the frc is in a gist here

-- EDIT 2 --

Starting a bounty for anyone that can point me in the right direction on this.

-- Edit 3 --

As requested, here is the code for my Delegate Methods:

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

-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)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)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    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:
            if (!self.searchIsActive) {
                [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            } else {
                [self.searchDisplayController.searchResultsTableView reloadData];
            }
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    } 
}


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

}

And the info got my Data Model:

// Person.h
#import <CoreData/CoreData.h>
@interface Person :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * company;
@property (nonatomic, retain) NSString * comments;
@property (nonatomic, retain) NSString * job;
@property (nonatomic, retain) NSDate * logDate;
@property (nonatomic, retain) NSString * location;
@property (nonatomic, retain) NSNumber * rating;
@property (nonatomic, retain) NSString * imagePath;
@property (nonatomic, retain) NSString * thumbPath;

@end

// Person.m
#import "Person.h"

@implementation Person 

@dynamic name;
@dynamic company;
@dynamic comments;
@dynamic job;
@dynamic logDate;
@dynamic location;
@dynamic rating;
@dynamic imagePath;
@dynamic thumbPath;

@end

Info about the data model:

Entity: Person
    Property: comments
        kind: attribute
        type: string
        optional: YES
    Property: name
        kind: attribute
        type: string
        optional: NO
    Property: rating
        kind: attribute
        kind: Int 16
        optional: YES
        min value: 0
        max value: 5
    Property: job
        kind: attribute
        kind: string
        optional: YES
    Property: company
        kind: attribute
        kind: string
        optional: YES
    Property: location
        kind: attribute
        kind: string
        optional: YES
    Property: imagePath
        kind: attribute
        kind: string
        optional: YES
    Property: thumbPath
        kind: attribute
        kind: string
        optional: YES
    Property: logDate
        kind: attribute
        kind: date
        optional: YES

Nothing too special about any of this.

Answers


I am reposting this comment as answer, as requested.

Both the "job" and "location" attributes are optional. Does the new item you add in one of the broken configuration actually contain values for these attributes? It may be that an item is not added to the table because, owing to its attributes values and your NSFetchedResultsController setup, it is simply not fetched at all. For the same reasons, it may be that, once edited, an item disappear from the table (because it no longer belong to the table after editing).

EDIT:

To set an initial value different from nil, in your Core Data Person.m file add the following method

- (void) awakeFromInsert{
    self.job = @"";
    self.location = @"";
}

etc. This way, the initial values will be automatically inserted by Core Data each time you create a new person object.


Need Your Help

Application call authentication

flash facebook web-applications vk

my knowledge of flash and other web technologies isn't that good, but I was wondering, how do sites with their own API for applications (e.g. Facebook) authenticate calls from an application? I'm not

How to build only a handful of projects contained in a solution using MSBuild?

.net tfs msbuild team-build

I am trying to setup a TFS Team Build and am new to MSBuild. I have a solution that contains a few projects (MyProject1, MyProject2, ..). I find that setting up the team build I could only select w...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.