views:

3215

answers:

2

I am placing an NSFetchedResultsController into my code so I get that nice automatic sectioning of my table view data.

So I am running a test to make sure everything works properly. I have a single Book entity in my persistent store. I will first perform the fetch the old way, then I will try to use NSFetchedResultsController. The difference between the 2 blocks of code is just 2 lines.

Code without NSFetchedResultsController:

 NSFetchRequest *request = [[NSFetchRequest alloc] init];
 NSEntityDescription *entity = [NSEntityDescription entityForName:kBookEntityName inManagedObjectContext:self.managedObjectContext];
 [request setEntity:entity];

 NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
 [request setSortDescriptors:sortDescriptors];
 [sortDescriptor release];
 [sortDescriptors release];

  //The following 2 lines will be replaced by the NSFetchedResultsController
 NSMutableArray *mutableFetchResults = [[[self.managedObjectContext executeFetchRequest:request error:nil] mutableCopy] autorelease];
 Book *result = (Book*)[mutableFetchResults objectAtIndex:0];

 NSString* title = [result valueForKey:@"title"];
 NSString* priority = [result valueForKeyPath:@"priority.name"];


 [request release];

Now I substitute in the lines for the NSFetchedResultsController:

NSFetchedResultsController* fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"title" cacheName:@"BookList"];                                                                                                                                                                                                                                                                                                           

Book *result = (Book*)[fetchedResultsController objectAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];

Seems pretty cut and dry. The first code block properly fetches the single Book entity. The code with the NSFetchedResultsController, however, does not. Instead it returns nil.

My question is: Am I properly configuring the NSFetchedResultsController in this example?

(note, the fetchedObjects property of the NSFetchedResultsController is also nil)

+5  A: 

I think you still need to tell the NSFetchedResultsController to actually perform the fetch:

NSError *error;
BOOL success = [controller performFetch:&error];

(taken from the example in the NSFetchedResultsController reference)

one other thing that seems odd: do you really want to use "title" as the sectionNameKeyPath? won't that basically create a separate section for each book?

David Maymudes
the "title" organization is just a test to get it up and running. I actually want to section by a key path on the authors name, but want to get it working with a simple example.
Corey Floyd
That is pretty sad that I didn't actually perform the fetch. I don't know why I assumed the fetch was performed on initialization.Thanks
Corey Floyd
+5  A: 

You need to initialize your NSFetchedResultsController only once, as follows.The code assumes

NSFetchedResultsController *fetchedResultsController;
NSManagedObjectContext *managedObjectContext;

are declared in the header of your controller, and that managedObjectContext is already properly initialized.

- (void)viewDidLoad {

    [super viewDidLoad];

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) {
     // Handle error
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]);

    }

    NSLog(@"%d objects fetched", [[fetchedResultsController fetchedObjects] count]);
}

- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController != nil) {
        return fetchedResultsController;

    }

    /*
     Set up the fetched results controller.
     */



    // Create the fetch request for the entity.
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:kBookEntityName inManagedObjectContext:self.managedObjectContext];
    [request setEntity:entity];

/* Optional settings

    [request setResultType:NSManagedObjectResultType];
    [request setIncludesPropertyValues:YES];
    [request setIncludesPendingChanges:NO];
    [request setReturnsObjectsAsFaults:NO];
*/  


    // Edit the sort key as appropriate.
     NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO];
 NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
 [request setSortDescriptors:sortDescriptors];
 [sortDescriptor release];
 [sortDescriptors release];;

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:managedObjectContext sectionNameKeyPath:@"title" cacheName:@"BookList"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [request release];


    return fetchedResultsController;
}
unforgiven