我会很感激一些指导,因为我对核心数据问题有点不了解。我喜欢使用NSSortDescriptor创建NSFetchRequest,NSSortDescriptor使用基于多对多关系的依赖属性。
对于Apple来说,文档说你不能这样做。让我感到困惑的是,只有当我将它作为NSSortDescriptor的一部分使用时才会起作用。在请求的NSPredicate和我的ManagedObject子类中,它可以工作。
简而言之,我有一个简单的对象模型,它包含一个可以有许多Checkin对象的Venue对象。每个Checkin对象都有一个名为hereNow的属性。
@interface Venue : NSManagedObject <MKAnnotation> {}
@property (nonatomic, readonly, retain) NSNumber * hereNow;
@end
@interface Venue (CoreDataGeneratedAccessors)
- (void)addCheckinsObject:(NSManagedObject *)value;
- (void)removeCheckinsObject:(NSManagedObject *)value;
- (void)addCheckins:(NSSet *)value;
- (void)removeCheckins:(NSSet *)value;
@end
@implementation Venue
- (NSNumber *)hereNow {
return [self valueForKeyPath:@"checkins.@sum.hereNow"];
}
@interface Checkin : Update {}
@property (nonatomic, retain) Venue * venue;
@property (nonatomic, retain) NSNumber * hereNow;
@end
@implementation Checkin
@dynamic venue;
@dynamic hereNow;
@end
到目前为止一切顺利。这是来自TableView控制器的fetchRequest
// Create and configure a fetch request with the Venue entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Venue" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Create a predicate to filter the results
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"checkins.@sum.hereNow > 0"];
[fetchRequest setPredicate:predicate];
// Create the sort descriptors array.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"checkins.@sum.hereNow" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:nil
cacheName:@"Venues"];
使用该代码,我得到以下错误
由于未捕获的异常'NSInvalidArgumentException'而终止应用程序,原因:'包含KVC聚合的Keepath不应该有一个;没办法办理登记手续。@ sum.hereNow'
但是我对MapView控制器有一个类似的fetchRequest,它完美地工作(我只是设置NSSortDecriptor使用name字段)。如果我对TableView fetchRequest执行相同的操作,那么它也会起作用,并且当添加新的签入对象时,Venue计数似乎会正确更新。所以在谓词中只使用sortDecriptor似乎没有问题。
Apple's documentation但是,这说; -
您无法在多对多关系中设置依赖关系。例如,假设您有一个Order对象,该对象具有与OrderItem对象集合的多对多关系(orderItems),而OrderItem对象具有price属性。您可能希望Order对象具有totalPrice属性,该属性取决于关系中所有OrderItem对象的价格。您不能通过实现keyPathsForValuesAffectingValueForKey:并返回orderItems.price作为totalPrice的键路径来完成此操作。您必须观察orderItems集合中每个OrderItem对象的price属性,并通过自己更新totalPrice来响应其值的变化。
这看起来很清楚,但后来我不明白为什么我可以在谓词中做同样的事情?这是我的第一个核心数据应用,所以我对它有点新意。我已经阅读了几个关于KVO,KVC等的问题,我还没有真正掌握这些问题。正如你所看到的,我真正想要做的就是根据他们派生的总数“hereNow”对一组场地进行排序。也许我会以完全错误的方式解决这个问题?如果是这样的话,那将是一个正确方向的友好指导!
答案 0 :(得分:3)
我能想到的一些事情:
在SortDescriptor上,您不能使用@sum来计算排序值。你必须在其他地方计算。我相信这就是为什么它说“含有KVC聚合物”。因为您使用“键”值来创建排序描述符,所以它必须是对象的实际属性。
如果Venue对象中有派生属性,则不应使其依赖于遍历关系的其他对象。您的“hereNow”属性无法遍历Checkin对象以获取要在Venue对象上返回的值。我相信派生属性只允许访问同一对象中的其他属性。
尝试一种可能的方法是将排序描述符键更改为尝试initWithKey:@“hereNow”。
它与MapView控制器一起工作的原因(我从你的问题推断)是名称字段在同一个对象上,并且不会遍历关系以获得该值。
我可以建议的最好的事情是在Venue对象上添加一个实际属性,每次更改Checkins时都会更新。我知道这不是你想要的,但它会起作用。
顺便说一句,keyPathsForValuesAffectingValueForKey可以在Mac上运行,但不适用于iOS。它会告诉父对象何时需要更新。请参阅:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVODependentKeys.html#//apple_ref/doc/uid/20002179-BAJEAIEE
的“注册从属密钥”部分如果您是CoreData的新手,我会推荐Marcus Zarra写的一本好书:https://pragprog.com/titles/mzcd/core-data
希望这有帮助。