Привязки какао: привязка к «многим» концам отношения ко многим - PullRequest
3 голосов
/ 30 сентября 2010

Используя пример Employees-Departments, я хочу привязать столбец к «Departments.arrangedObjects.employees. @ Sum.hoursWorked», как показано ниже:

Entity Employee

  • атрибуты: «firstName», «lastName», «hoursWorked»
  • отношение: «отделы»

Отдел сущностей

  • атрибуты: «имя"
  • отношение:" сотрудники "

Мне нужна таблица, которая будет отображать некоторую сводную информацию об отделах.

Я связываю первый столбец с моим контроллером массива "Departments", "agedObjects.name ".У меня может быть столбец, отображающий количество сотрудников в отделе, с помощью привязки к "builtObjects.employees. @ Count"

Однако я не могу получить сумму часов, отработанных сотрудниками, как я полагаю, я мог бы связатьto "selectedObjects.employees. @ sum.hoursWorked"

Я получаю сообщение об ошибке "[<_NSFaultingMutableSet 0x1acea0> addObserver: forKeyPath: options: context:] не поддерживается. Путь ключа: @sum.hoursWorked "

Я полагаю, что это потому, что невозможно связать многие отношения со многими.Если да, как я могу делать то, что хочу?

Для дополнительного кредита, скажем, у каждого сотрудника есть еще один атрибут, «раса», я также хотел бы, чтобы в моей таблице итогов отображалось количество уникальных рас в каждомотдел.

Заранее спасибо.

1 Ответ

1 голос
/ 06 января 2012

Я столкнулся с теми же ошибками, что и вы. Кажется, что в то время как вы можете получить набор сотрудников и выполнить некоторые совокупные операции над ним, сделав что-то вроде:

Отдел * Отдел =; NSSet * employee = dept.employees; NSNumber * sumOfHoursWorked = [сотрудники valueForKeyPath: @ "@ sum.hoursWorked"];

Есть разница, когда вы связываете. Привязки просят наблюдать путь ключа, а не оценивать его один раз. Принимая во внимание, что вроде как, есть смысл, почему вы не можете связать эти ключевые пути. Своего рода. Сорта.

Теперь. Что касается решения, то, что я обычно делаю в таких случаях, это напишу крошечный маленький подкласс NSValueTransformer, чтобы делать то, что мне нужно, а затем подключить это к IB. Таким образом, я пишу десять строк кода, которые мне нужны, но не заканчиваю тем, что выполняю весь набор источников данных NSTableView из-за отсутствия простого агрегата. В этом случае вы можете сделать что-то вроде этого:

// Declaration

@interface MySumOfHoursWorkedTransformer : NSValueTransformer
@end

@interface MyNumberOfRacesTransformer : NSValueTransformer
@end

// Implementation


@implementation MySumOfHoursWorkedTransformer

+ (Class)transformedValueClass { return [NSNumber class]; }   // class of the "output" objects, as returned by transformedValue:
+ (BOOL)allowsReverseTransformation { return NO; }    // flag indicating whether transformation is read-only or not

- (id)transformedValue:(id)value           // by default returns value
{
    NSNumber* retVal = nil;
    if ([value isMemberOfClass: [Department class]])
    {
        double hoursWorked = 0.0;
        for (Employee* employee in [value valueForKey: @"employees"])
        {
            NSNumber* hoursWorkedNumber = employee.hoursWorked;
            hoursWorked += hoursWorkedNumber ? [hoursWorkedNumber doubleValue] : 0.0;
        }
        retVal = [NSNumber numberWithDouble: hoursWorked];
    }
    return retVal;
}

@end

@implementation MyNumberOfRacesTransformer

+ (Class)transformedValueClass { return [NSNumber class]; }   // class of the "output" objects, as returned by transformedValue:
+ (BOOL)allowsReverseTransformation { return NO; }    // flag indicating whether transformation is read-only or not

- (id)transformedValue:(id)value           // by default returns value
{
    NSNumber* retVal = nil;
    if ([value isMemberOfClass: [Department class]])
    {
        NSMutableSet* raceSet = [NSMutableSet set];
        for (Employee* employee in [value valueForKey: @"employees"])
        {
            id raceVal = employee.race;
            if (raceVal)
                [raceSet addObject: raceVal];
        }
        retVal = [NSNumber numberWithUnsignedInteger: raceSet.count];
    }
    return retVal;
}

@end

Затем просто привяжите эти TableColumns к ArrayController.arrangedObjects и подключите соответствующий подкласс преобразователя значения. Теперь вы не сможете редактировать эти значения, но что бы это значило для редактирования совокупного значения?

Надеюсь, это поможет. Я использовал этот подход кучу, и он наверняка превосходит отказ от привязок.

...