Основные данные - построение NSP-предиката из отношения ManyToMany - PullRequest
0 голосов
/ 23 марта 2011

Это дополнительный вопрос к моему предыдущему вопросу:

Основные данные: Управление контрактами сотрудников в отношениях «многие ко многим»?

Естьдиаграмма по этому вопросу, и в качестве быстрого напоминания есть следующее:

company --< contracts >-- employees

Мне удалось вручную сохранить 1 сущность в каждой из сущностей и проверить их всев NSLog.

Я создал CompanyListPage, в котором перечислены все компании.Идея заключается в том, что при нажатии на компанию вам будет представлен список всех сотрудников, которые имеют контракт с указанной компанией.

В контексте см. Ниже:

Company: 
name: A

Contract:
length: 33 wks
salary: 20000

Employee:
name: Bob Jones

В моемСтраница didSelectRowAtIndex в моей CompanyListPage У меня есть следующее.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {


    Company *c = [fetchedResultsController objectAtIndexPath:indexPath];    
    NSLog(@"You clicked %@", c.name);
    NSString *companyName = c.name;

    EmployeesListPage *employeesListPage = [[EmployeesListPage alloc] initWithNibName:@"EmployeesListPage" bundle:[NSBundle mainBundle]];

    [self.navigationController pushViewController:employeesListPage animated:YES];

    employeesListPage.title = companyName;  
    employeesListPage.managedObjectContext = self.context;
    employeesListPage.managedObject = c;

    [superstarsList release];

}

Проблема, однако, заключается в том, что я не уверен, как должен выглядеть мой NSPredicate, когда я в конечном итоге захожу на employeeListPage.

Вмомент, это это:

- (NSFetchedResultsController *)fetchedResultsController 
{

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    // Create and configure a fetch request
    NSFetchRequest *fetchRequest    = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity     = [NSEntityDescription entityForName:@"Employees" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    // Create the sort descriptors array
    NSSortDescriptor *authorDescriptor  = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:authorDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    // Create and initialize the fetch results controller
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    self.fetchedResultsController = aFetchedResultsController;
    fetchedResultsController.delegate = self;

    // Memory management.
    [aFetchedResultsController release];
    [fetchRequest release];
    [authorDescriptor release];
    [sortDescriptors release];

    return fetchedResultsController;
}    

Очевидно, что это неправильно, потому что это не так:

a) Поиск в объекте контракта б) Использование объекта компании любым способом, в той или иной форме

Я знаю, что мне нужно использовать NSP-предикат, но я просто знаю, как заставить его сказать «Найдите мне всех сотрудников с контрактом> 0 и работающим с компанией А», затем закажите его по имени человекапо убыванию или даже упорядочите сначала по наименьшей длине контракта.

Любые указатели или помощь по этому вопросу были бы хорошими.Спасибо.


РЕДАКТИРОВАТЬ: Первая попытка (удалено, потому что я получил его на работу после ответа ниже)

РЕДАКТИРОВАТЬ: Не удалось получить информацию о контракте обратно?

Мне удалось вернуть всех сотрудников, которые работают в компании А, в мой контроллер табличного представления.

Однако я хочу отобразить в своей ячейке информацию о сотруднике и его контрактной длине / зарплате.

Я пробовал следующее:

Employee *emp = [fetchedResultsController objectAtIndexPath:indexPath];


NSString *firstname = emp.firstname;
NSString *surname = emp.surname;

NSString *fullname = [firstname stringByAppendingString:@" "];
fullname = [fullname stringByAppendingString:surname];

// Logging tests
NSLog(@"Name: %@", fullname); // This is fine
NSLog(@"Contracts: %@", emp.empContracts);  // This tells me of a problem with "Relationship fault for <NSRelationshipDescription: 0x602fdd0>"

Iполагаю, что мне нужно получить NSPredicate для сбора всех данных контракта, а не только данных контракта;однако я могу ошибаться.

Опять же, помощь по этому вопросу будет принята с благодарностью.

Ответы [ 3 ]

1 голос
/ 23 марта 2011

Я думаю, что если вы используете ключевое слово ANY, вы восстановите левую часть уравнения до одной величины, которая будет соответствовать правой части уравнения:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@“ANY contracts.employer ==  %@“, employer];
0 голосов
/ 24 марта 2011

Похоже, все идет хорошо. Я думаю, что все, что вам нужно, это установить текст ячейки: cell.textLabel = fullname.

Но я не понимаю, почему вы углубляетесь в договорные отношения - пока я не посмотрю ваш образец текста вверху. Там, похоже, вам нужен список контрактов для работодателя, и для каждого контракта вы хотите показать свои отношения с одним сотрудником и другими субъектами. В этом случае вам вообще не нужен новый выбор; у вас уже есть работодатель, и благодаря его отношениям со многими контрактами у вас также есть контрактные организации и через них срок, зарплата, работник и т. д.

При изменении выбора в таблице работодателей вы должны сделать что-то вроде этого:

NSUInteger row = [indexPath row];
Employer *employer = [self.arrayOfEmployersUsedToPopulateTable objectAtIndex:row];
self.selectedEmployer = employer;
self.arrayOfSelectedEmployersContracts = [employer.contracts allObjects]; // which probably faults them, but I think that’s OK here
// Then make a call to reload the other table, the one presenting the contracts info.

В таблице контрактов вы вернетесь к выбранному работодателю и представите информацию для каждого контракта:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
Contract *contract = [self.arrayOfSelectedEmployersContracts objectAtIndex:row];
NSUInteger column = [indexPath column];
switch (column) {
    (0) :
    cell.textLabel = contract.length; // maybe you have to use an NSNumber method to convert to string, but probably not
    break;
    (1):
    cell.textLabel = contract.employee.firstname;
    break;
    // and so forth
}}

P.S. Что касается материала UITableCell, я проконсультировался с Марком и Ламаршем «Начало разработки iPhone»: «Использование новой ячейки табличного представления». Вам может понравиться и эта книга.

0 голосов
/ 24 марта 2011

Я думаю, что у меня есть ответ.

Я сделал следующее в своем табличном представлении и получил правильное отношение и весь вывод; однако я не уверен, правильно ли я это делаю, потому что это включает цикл for.

Я использовал следующий связанный со StackOverflow вопрос / ответ для своего решения.

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath 
{
    Employee *emp = [fetchedResultsController objectAtIndexPath:indexPath];

    NSString *firstname = emp.firstname;
    NSString *surname   = emp.surname;

    NSString *fullname  = [firstname stringByAppendingString:@" "];
    fullname            = [fullname stringByAppendingString:surname];

    NSLog(@"Employee: %@", fullname);

    // Output the contract deals.
    for (Contracts *deals in emp.contracts) 
    {

        NSNumber *cLength   = deals.length;
        NSNumber *cSalary   = deals.salary;

        NSLog(@"Length: %@", cLength);
        NSLog(@"Salary: %@", cSalary);
    } // next
}

Следующий шаг для меня - включить это в пользовательское представление с пользовательскими метками для хранения всей этой информации.

Если цикл for не самый эффективный способ сделать это, я приветствую любые предложения / улучшения или даже то, что считается наилучшей практикой.

Спасибо.

...