在NSTableView的自定义NSCell中使用绑定公开模型对象

时间:2010-04-17 06:53:14

标签: objective-c nstableview cocoa-bindings nsarraycontroller nscell

我正在努力尝试执行我认为相对常见的任务。我有NSTableView通过NSArrayController绑定到它的数组。数组控制器将其内容设置为NSMutableArray,其中包含一个或多个模型类的NSObject个实例。我不知道怎么做是以一种友好绑定的方式在NSCell子类中公开模型。

出于说明的目的,我们将说对象模型是由名字,姓氏,年龄和性别组成的人。因此,模型看起来像这样:

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

显然适合该类的setter,getter init等。

在我的控制器类中,我定义了NSTableViewNSMutableArrayNSArrayController

@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对象。但我不知道怎么做到这一点。我不想使用setter和getter设置每个NSCell,因为我通过在NSCell中存储数据而不是从数组控制器引用它来打破整个模型概念。

是的,我确实需要自定义NSCell,因此不能选择多列。从哪里来?

除了Google和StackOverflow搜索之外,我已经完成了对Apple的文档的强制性演练,似乎没有找到答案。我发现很多参考文献都围绕着丛林,但没有涉及NSArrayController。当绑定到模型实体的其他元素(例如主/细节场景)时,控制器使生活变得非常容易。我在使用Core Data时也发现了很多引用(虽然没有答案),但我没有使用Core Data。

根据常规,我非常感谢能提供任何帮助!

3 个答案:

答案 0 :(得分:3)

最后想出了这个。采取一些做的人。所以这就是我需要做的......

首先,我需要在模型对象中创建模型的键值数组,并在模型中的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 :(得分:1)

还有另一种方法不需要字典。但是,它确实需要在数据类中实现 - (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中,您将Table Column的值指向Array Controller - > arrangedObjects

drawWithFrame方法现在将从objectValue返回您的实际对象。

Activity *rowActivity = [self objectValue];

更改类需要更新copyWithZone方法,然后直接在drawWithFrame方法中访问数据。

答案 2 :(得分:0)

我非常感谢这篇文章,Hooligancat,因为我的项目在这个问题上停滞不前,而且我在http://www.timisted.net/blog/archive/custom-cells-and-core-data/时看到Tim Isted的相同解决方案一样困难 我无法理解。

只有当我读到您对问题的简单简化以及您的解决方案版本时,便士才会放弃 - 我非常感激!