0

I have 2 entities in my Core Data database Person and Photo a Person has a To-Many relationship with Photo and Photo has a reverse relationship with Person (Person<-->>Photo). I load some initial data for my app off a .plist in the following manner:

-(void)populateDataStorage{

    NSString *path = [[NSBundle mainBundle] pathForResource:@"FakeData" ofType:@"plist"];

    if(path){
        NSArray *plistData = [[NSArray alloc] initWithContentsOfFile:path];
        NSEnumerator *enumerator = [plistData objectEnumerator];

        NSArray *personResults;

        Photo *photo;
        Person *person;

        id currItem = [enumerator nextObject];

        while (currItem != nil) {
            photo = (Photo *)[NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:[flickrFetcher managedObjectContext]];

            photo.name = [currItem objectForKey:@"name"];
            photo.path = [currItem objectForKey:@"path"];

            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", [currItem objectForKey:@"user"]];

            personResults = [flickrFetcher fetchManagedObjectsForEntity:@"Person" withPredicate:predicate];

            if ([personResults count] > 0) {
                person = [personResults objectAtIndex:0];
            } 
            else {
                person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:[flickrFetcher managedObjectContext]];
                person.name = [currItem objectForKey:@"user"];
            }

            photo.person = person;
            [person addPhotosObject:photo];

            NSLog(@"Photo %@ added for user %@", photo.name, person.name);

            currItem = [enumerator nextObject];
        }

        [plistData release];

    }

}

Everything loads properly. Then I use a NSFetchedResultsController to get the Person and load a UITableView and it all works. When the user clicks on a cell that belongs to a user I have to load another UITableView with the selected Person's Photos, so I do the following in my UITableViewController for my Photo's table view:

 - (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person = %@", person];
        self.fetchedResultsController = [[FlickrFetcher sharedInstance] fetchedResultsControllerForEntity:@"Photo" withPredicate:predicate];
    }
    return self;
}

And in my viewDidLoad :

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSError *error = nil;
    [fetchedResultsController performFetch:&error];

    for(Photo *photo in person.photos){
        NSLog(@"Photo %@ belongs to %@", photo.name, person.name);
    }

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

The count is giving me 0, i never get the Person's Photos but I know they are properly saved because they all print out for the passed in Person. Any idea what I might be doing wrong?

EDIT

Utility method for getting the NSFetchedResultsController in my FlickrFetcher class:

- (NSFetchedResultsController *)fetchedResultsControllerForEntity:(NSString*)entityName withPredicate:(NSPredicate*)predicate {
    NSFetchedResultsController *fetchedResultsController;

    /*
     Set up the fetched results controller.
     */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

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

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Add a predicate if we're filtering by user name
    if (predicate) {
        [fetchRequest setPredicate:predicate];
    }

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

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

    return [fetchedResultsController autorelease];
}

My own NSFetchedResultsController created in my UITableViewController:

NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Photo" inManagedObjectContext:[flickFetcher managedObjectContext]];

    [request setEntity:entity];

    NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:descriptor, nil];

    [request setSortDescriptors:sortDescriptors];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"person = %@", person];

    [request setPredicate:predicate];

    fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:[flickFetcher managedObjectContext] sectionNameKeyPath:nil cacheName:@"Root"];

    [request release];
    [descriptor release];
    [sortDescriptors release];

    NSError *error = nil;
    [fetchedResultsController autorelease];
    [fetchedResultsController performFetch:&error];

I don't see the difference.

1 Answer 1

1

Don't see anything offhand. I'd want to insert a save on the context after I inserted all the test data. (And not insert it next time around.)

One comment:

photo.person = person;
[person addPhotosObject:photo];

this is redundant. A relationship that is modeled with a reverse relationship in core data will correctly set the reverse relationship, if you set the other. So, only one of these lines is needed.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the tip I managed to retrieve the Photos from the context which is weird because all I did was create my own fetched results controller that doesn't differ from the utility method I had before, but now the table cells aren't set, cellForRowAtIndex is never called for some reason, I will update the code to show both fetchedResultsControllers.
no cellForRowAtIndex: = no tableView.dataSource, or numberOfRowsInSection = 0
was the numberOfRowsInSection deal, that did the trick. Notice any difference in my fetchedResultsControllers? Besides the ascending parameter

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.