这不是一个简单的问题。事情是,Core Data不知道numKm
作为一个属性。它应该如何知道numKm
对应于特定的CarProperty
对象?
您正在描述的基本问题是键值编码合规性。 Cocoa将在properties
对象上寻找一种叫做numKm
的方法。没有找到一个,它会尝试发送[properties valueForKey:@"numKm"];
由于valueForKey:
不知道该怎么做numKm
,你会得到一个错误,而不是它调用[properties valueForUndefinedKey:@"numKm"]
但这里的渔获前:properties
是核心数据生成的NSSet
,所以你不能继承它来覆盖valueForUndefinedKey:
。你可以做的是创建你自己的对象,它符合你的任意属性的KVC标准并使用它。
一种解决方案是将子类NSDictionary
并使其充当代理。原始方法是count
,objectForKey:
和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
发生变化,您将无法观察到这一点。你需要做一些额外的工作才能做到这一点。
非常感谢!这使我非常喜欢一个方向!很高兴知道我不会通过简单的解决方案重新解决常见问题。 – 2010-06-12 10:24:20
这个答案是完全正确的,但是,我不得不问,为什么你使用Core Data只是为了抛弃它的权力?如果你有一个汽车实体,有些事情应该是属性,其他事情应该是关系。例如,numKm应该是float或int,因为它很可能不会经常在汽车之间重复。另一方面,制造商应该完全是与制造商实体的关系。您甚至可以使用绑定来查看特定制造商的所有汽车。 – theMikeSwan 2010-06-16 01:32:43
我不能说OP的情况,但在我的情况下,属性直到运行时才知道。我的应用程序从Web服务器下载对象列表,其中列表可以具有任意类型的任意列。除了保证存在的一些属性以及我为其创建属性外,其余所有属性在数量和类型上都是可变的。 – Alex 2010-06-16 14:54:58