views:

505

answers:

1

Folks,

I've got a bit of a puzzler involving Core Data in my iPhone project. During the viewDidLoad method in two separate view controller instances I call the following method:

- (NSFetchedResultsController *)getStudentResults:(NSString *)classRoom forWeekStarting:(NSDate *)startDate andEnding:(NSDate *)endDate {
    AttendanceAppDelegate *appDelegate = (AttendanceAppDelegate *)[[UIApplication sharedApplication] delegate];

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:[appDelegate managedObjectContext]];

    int secondsInAWeek = 60 * 60 * 24 * 7;
    NSDate *today = [[NSDate alloc] init];
    NSDate *nextWeek = [[NSDate alloc] initWithTimeIntervalSinceNow:secondsInAWeek];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(student.classRoom like %@) AND (dateTime >= %@) AND (dateTime <= %@)", classRoom, startDate, endDate];
    [request setPredicate:predicate];
    [request setEntity:entityDescription];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dateTime" ascending:YES];
    NSArray *descriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:descriptors];
    [descriptors release];
    [sortDescriptor release];
    [nextWeek release];
    [today release];


    NSFetchedResultsController *fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[appDelegate managedObjectContext] sectionNameKeyPath:nil cacheName:@""];
    NSError *error; 
    if (![fetchedResultsController performFetch:&error])
     NSLog(@"Error performing fetch on fetchedResultsController: %@", [error localizedDescription]);

    if (fetchedResultsController == nil || [[fetchedResultsController fetchedObjects] count] == 0) { 
     Student *student = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:[appDelegate managedObjectContext]];
     NSData *classRoomStudentData = [[NSData alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"STUDENT_ATTENDANCE" ofType:@"XML"]];
     [student setClassRoom:@"default"];
     [student buildWithStudentData:classRoomStudentData startingWithXPathNode:@"//attendance"];

     NSError *error; 
     if (![[appDelegate managedObjectContext] save:&error]) { 
      NSLog(@"Error saving the managedObjectContext: %@", [error localizedDescription]);
     }

     if (![fetchedResultsController performFetch:&error])
      NSLog(@"Error performing fetch on fetchedResultsController: %@", [error localizedDescription]);
    }
    return fetchedResultsController;
}

Each time I run my app the number of Student objects increases by the number of original entities (each original entity is duplicated once). So if I start with 4, the next time I get 8, then 12, then 16, etc. I can't seem to figure out why since the code to parse the XML only gets called when the fetch returns no objects.

Any help would be appreciated, thanks.

-- Michael

+1  A: 

You insert the new objects not just when the fetch returns no objects: looking at your code

if (fetchedResultsController == nil || [[fetchedResultsController fetchedObjects] count] == 0)

you also insert them when you fail to correctly initialize your NSfetchedResultsController. Therefore, if you repeatedly fail to initialize it correctly, each time you add new objects.

A suggestion is to initialize the NSfetchedResultsController as shown in all of the sample code provided by Apple. Basically, you start by verifying if the fetchedResultsController is nil or not. If not, you simply return the variable. Otherwise, you initialize it.

See my answer to this question for an example:

How to properly configure NSFetchedResultsController

unforgiven
You're absolutely right, I just stepped through the code a second time and discovered that when asking for a classRoom other than "default" the XML would be parsed again. Thanks for the pointer.
Michael Fey