我是核心数据新手,我遇到了一个问题,我无法理解如何以“正确的方式”进行操作
我会尝试举例说明我的问题。
我有一辆实体汽车。以及我的程序中所有汽车的列表。汽车有一些属性,但它们不是预定义的。因此,对于每辆车,我希望能够定义一些属性。 因此,我定义了一个新的实体 CarProperty,与汽车具有一对多的关系。
在 nscollectionview 中,我想显示汽车的一些属性,更具体的是它行驶的公里数 (numKm)(如果该属性存在)。所以我想将它绑定(bind)到标签上。但怎么办呢?
我不能说representedObject.properties.numKm
,或representedObject.numKm
。
我应该如何解决这个问题?
希望这是有道理的。
最佳答案
这不是一个简单的问题。问题是,Core Data 对 numKm
作为属性一无所知。它如何知道 numKm
对应于特定的 CarProperty
对象?
您描述的根本问题是键值编码合规性。 Cocoa 将在 properties
对象上查找名为 numKm
的方法。如果找不到,它将尝试发送 [properties valueForKey:@"numKm"];
因为 valueForKey:
不知道如何处理 numKm
时,您会收到错误,但在调用 [properties valueForUndefinedKey:@"numKm"]
但这里有一个问题:properties
是由 Core Data 生成的 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
发生变化,您将无法观察到这一点。您需要做一些额外的工作才能实现这一点。
关于objective-c - 绑定(bind)到 Core Data 中的关系属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3024767/