2010-06-11 113 views
0

我的核心数据是新的,和我有一个问题,我不能让我围绕着如何做“正确的方式”绑定到一个核心属性的关系数据

我会尽力和examplify头我的问题。

我得到了一个实体车。还有我的程序中的所有汽车的列表。汽车有一些属性,但它们不是预定义的。所以对于每辆车我都希望能够定义一些属性。 因此,我定义了一个新的实体CarProperty,与汽车有一对多的关系。

在nscollectionview中,我想展示汽车的一些属性,更具体说明它驱动的公里数(numKm)(如果该属性存在)。所以我想将它绑定到一个标签。但怎么办?

我不能说representedObject.properties.numKmrepresentedObject.numKm

我该如何解决这个问题?

,真希望是有道理的。

回答

1

这不是一个简单的问题。事情是,Core Data不知道numKm作为一个属性。它应该如何知道numKm对应于特定的CarProperty对象?

您正在描述的基本问题是键值编码合规性。 Cocoa将在properties对象上寻找一种叫做numKm的方法。没有找到一个,它会尝试发送[properties valueForKey:@"numKm"];由于valueForKey:不知道该怎么做numKm,你会得到一个错误,而不是它调用[properties valueForUndefinedKey:@"numKm"]

但这里的渔获前:properties是核心数据生成的NSSet ,所以你不能继承它来覆盖valueForUndefinedKey:。你可以做的是创建你自己的对象,它符合你的任意属性的KVC标准并使用它。

一种解决方案是将子类NSDictionary并使其充当代理。原始方法是countobjectForKey:keyEnumerator。如果您重写这三种方法,则可以创建一个链接到您的Car对象的NSDictionary,并返回相应的CarProperty对象。例如:

@interface PropertyProxy : NSDictionary { 
} 
@property (nonatomic, readonly, assign) Car *car; 

- (id)initWithCar:(Car *)car 

@end 

@implementation PropertyProxy 

@synthesize car = _car; 

- (id)initWithCar:(Car *)car { 
    if (!(self = [super init])) 
     return nil; 

    _car = car; 

    return self; 
} 

- (NSInteger)count { 
    return [car.properties count]; 
} 

- (id)objectForKey:(NSString *)key { 
    return [[car.properties filteredSetUsingPredicate:[NSPredicate predicateWithFormt:@"key == %@", key]] anyObject]; 
} 

- (NSEnumerator *)keyEnumerator { 
    return [[car valueForKeyPath:@"properties.key"] objectEnumerator]; 
} 

@end 

然后,在你Car类,这样做:

@interface Car : NSManagedObject { 
    // other stuff 
} 

@property (nonatomic, readonly) NSDictionary *carProperties; 

// other stuff 

@end 

@implementation Car 

// other stuff 

- (NSDictionary *)carProperties { 
    return [[[PropertyProxy alloc] initWithCar:self] autorelease]; 
} 

@end 

(声明:我刚才输入到这个网页浏览器,所以不能保证这实际上编译:-))

正如你所看到的,这不是世界上最简单的事情。您可以设置主要路径是这样的:

representedObject.carProperties.numKm; 

请记住,虽然这是一个键值编码标准,它不是键值观察标准。所以如果numKm发生变化,您将无法观察到这一点。你需要做一些额外的工作才能做到这一点。

+0

非常感谢!这使我非常喜欢一个方向!很高兴知道我不会通过简单的解决方案重新解决常见问题。 – 2010-06-12 10:24:20

+0

这个答案是完全正确的,但是,我不得不问,为什么你使用Core Data只是为了抛弃它的权力?如果你有一个汽车实体,有些事情应该是属性,其他事情应该是关系。例如,numKm应该是float或int,因为它很可能不会经常在汽车之间重复。另一方面,制造商应该完全是与制造商实体的关系。您甚至可以使用绑定来查看特定制造商的所有汽车。 – theMikeSwan 2010-06-16 01:32:43

+0

我不能说OP的情况,但在我的情况下,属性直到运行时才知道。我的应用程序从Web服务器下载对象列表,其中列表可以具有任意类型的任意列。除了保证存在的一些属性以及我为其创建属性外,其余所有属性在数量和类型上都是可变的。 – Alex 2010-06-16 14:54:58