Выборка сущностей со связями в Базовых данных - PullRequest
0 голосов
/ 09 июля 2011

В моей базе данных базовых данных есть 2 объекта Person, а Photo a Person имеет отношение To-Many с Photo, а Photo имеет обратную связь с Person (Person<-->>Photo).Я загружаю некоторые исходные данные для моего приложения из .plist следующим образом:

-(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];

    }

}

Все загружается правильно.Затем я использую NSFetchedResultsController, чтобы получить Person и загрузить UITableView, и все это работает.Когда пользователь нажимает на ячейку, принадлежащую пользователю, я должен загрузить еще одну UITableView с фотографиями выбранного человека, поэтому я выполняю в своем UITableViewController для представления моей фотографии в виде таблицы:

 - (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;
}

Ив моем 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]);
}

Счет дает мне 0, я никогда не получаю фотографии человека, но я знаю, что они должным образом сохранены, потому что все они распечатываются для переданных в Person.Любая идея, что я могу делать неправильно?

РЕДАКТИРОВАТЬ

Утилита для получения NSFetchedResultsController в моем FlickrFetcher классе:

- (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];
}

Мой собственный NSFetchedResultsController созданный в моем 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];

Я не вижу разницы.

1 Ответ

1 голос
/ 09 июля 2011

Ничего не вижу случайно. Я хотел бы вставить сохранение в контекст после того, как я вставил все тестовые данные. (И не вставляйте его в следующий раз.)

Один комментарий:

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

это избыточно. Отношение, которое моделируется с помощью обратной связи в основных данных, будет правильно устанавливать обратную связь, если вы установите другую. Итак, нужна только одна из этих строк.

...