Предоставление объекта модели с помощью привязок в пользовательском NSCell NSTableView - PullRequest
4 голосов
/ 17 апреля 2010

Я изо всех сил пытаюсь выполнить то, что, на мой взгляд, было бы относительно распространенной задачей. У меня есть NSTableView, который связан с его массивом через NSArrayController. Контроллер массива имеет свой контент, установленный на NSMutableArray, который содержит один или несколько NSObject экземпляров класса модели. Чего я не знаю, как это сделать, так это выставить модель внутри подкласса NSCell так, чтобы она была удобна для привязок.

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

@interface PersonModel : NSObject {
    NSString * firstName;
    NSString * lastName;
    NSString * gender;
    int * age;
}

Очевидно, что подходящие сеттеры, инициаторы get и т. Д. Для класса.

В моем классе контроллеров я определяю NSTableView, NSMutableArray и NSArrayController:

@interface ControllerClass : NSObject {
    IBOutlet NSTableView * myTableView;
    NSMutableArray * myPersonArray;
    IBOutlet NSArrayController * myPersonArrayController;
}

Используя Interface Builder, я могу легко привязать модель к соответствующим столбцам:

myPersonArray --> myPersonArrayController --> table column binding

Это отлично работает. Поэтому я удаляю лишние столбцы, оставляя один столбец скрытым, который связан с NSArrayController (это создает и сохраняет связь между каждой строкой и NSArrayController), так что я дохожу до одного видимого столбца в моем NSTableView и один скрытый столбец. Я создаю подкласс NSCell и помещаю соответствующий метод рисования для создания ячейки. В моем awakeFromNib я устанавливаю пользовательский NSCell подкласс:

MyCustomCell * aCustomCell = [[[MyCustomCell alloc] init] autorelease];
[[myTableView tableColumnWithIdentifier:@"customCellColumn"] 
     setDataCell:aCustomCell];

Это тоже отлично работает с точки зрения рисования. Я получаю свою ячейку, отображаемую в столбце, и она повторяется для каждого управляемого объекта в контроллере массива. Если я добавлю объект или удалю объект из контроллера массива, таблица обновится соответствующим образом.

Однако ... У меня сложилось впечатление, что мой объект PersonModel будет доступен из моего подкласса NSCell. Но я не знаю, как до него добраться. Я не хочу устанавливать каждый NSCell, используя сеттеры и геттеры, потому что тогда я нарушаю всю концепцию модели, сохраняя данные в NSCell вместо того, чтобы ссылаться на них из контроллера массива.

И да, мне нужно иметь пользовательский NSCell, поэтому использование нескольких столбцов не вариант. Куда отсюда?

В дополнение к поиску в Google и StackOverflow, я прошел обязательную проверку документов Apple и, похоже, не нашел ответа. Я нашел много ссылок, которые бьют вокруг куста, но ничего, включая NSArrayController. Контроллер упрощает жизнь при привязке к другим элементам модели (например, сценарий мастер / деталь). Я также нашел много ссылок (хотя ответов нет) при использовании Core Data, но я не использую Core Data.

Согласно норме, я очень благодарен за любую помощь, которая может быть предложена!

Ответы [ 3 ]

3 голосов
/ 21 апреля 2010

Наконец-то понял это. Человек, который занялся этим. Итак, вот что мне нужно было сделать ...

Прежде всего мне нужно было создать массив значений ключей моей модели в моем объекте модели и вернуть эти значения ключей в NSDictionary изнутри модели.

Таким образом, моя модель получила два новых метода следующим образом (на основе моего упрощенного примера выше):

+(NSArray *)personKeys
{
    static NSArray * personKeys = nil;
    if (personKeys == nil)
        personKeys = [[NSArray alloc] initWithObjects:@"firstName", @"lastName", @"gender", @"age", nil];

    return personKeys;
}

-(NSDictionary *)personDictionary
{
    return [self dictionaryWithValuesForKeys:[[self class] personKeys]];
}

После реализации я назначаю свой предел value в моей таблице на

arrayController --> arrangeObjects --> personDictionary.

Последний шаг - ссылаться на объект в NSCell drawWithFrame и использовать по мере необходимости следующим образом:

NSDictionary * thisCellObject = [self objectValue];

NSString * objectFirstName = [thisCellObject valueForkey:@"firstName"];
NSString * objectLastName = [thisCellObject valueForKey:@"lastName"];

И, как я надеялся, любое обновление объекта модели отражается в пользовательском NSCell.

1 голос
/ 14 февраля 2012

Существует еще один подход, который не требует словаря. Однако для этого требуется реализация метода зоны - (id) copyWithZone: (NSZone *) в вашем классе данных. Например:

- (id)copyWithZone:(NSZone *)zone {
    Activity *copy = [[self class] allocWithZone: zone];
    copy.activityDate = self.activityDate;
    copy.sport = self.sport;
    copy.sportIcon = self.sportIcon;
    copy.laps = self.laps;
    return copy; }

Теперь в IB вы указываете значение Столбца таблицы в Array Controller -> AgronidObjects

Метод drawWithFrame теперь будет возвращать ваш фактический объект из objectValue.

Activity *rowActivity = [self objectValue];

Изменение класса требует обновления метода copyWithZone и последующего доступа к данным непосредственно в вашем методе drawWithFrame.

0 голосов
/ 01 июня 2010

Я очень благодарен за этот пост, Hooligancat, потому что мой проект был остановлен по этой проблеме, и так же сильно, как я смотрел на идентичное решение Тима Истеда в http://www.timisted.net/blog/archive/custom-cells-and-core-data/ Я не мог понять это.

Только когда я прочитал ваше превосходное упрощение проблемы и вашу версию решения, что пенни упала - я очень благодарен!

...