Сортировка NSFetchRequest по зависимому свойству с использованием отношения ко многим

Был бы признателен за некоторые рекомендации, так как я немного не в своей глубине по проблеме с данными Core. Я бы хотел создать NSFetchRequest с NSSortDescriptor, который использует зависимое свойство на основе отношения ко многим.

Что касается Apple, в документации сказано, что вы не можете этого сделать. Что меня смущает, так это то, что он не работает только тогда, когда я использую его как часть NSSortDescriptor. В NSPredicate запроса и в моем подклассе ManagedObject он работает.

Короче говоря, у меня есть простая объектная модель, которая включает в себя объект Venue, у которого может быть много объектов Checkin. Каждый объект 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:@"[email protected]"];

}

@interface Checkin :  Update  {}

@property (nonatomic, retain) Venue * venue;
@property (nonatomic, retain) NSNumber * hereNow;

@end

@implementation Checkin 

@dynamic venue;
@dynamic hereNow;

@end

Все идет нормально. Вот fetchRequest от контроллера TableView

// 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:@"[email protected] > 0"];
[fetchRequest setPredicate:predicate];

// Create the sort descriptors array.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"[email protected]" 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, которого не должно быть; не удалось обработать чекины. @ sum.hereNow '

Но у меня есть аналогичный fetchRequest для контроллера MapView, который отлично работает (я просто установил NSSortDecriptor для использования поля имени). Если я сделаю то же самое для TableView fetchRequest, это тоже будет работать, и счетчики Venue будут правильно обновляться при добавлении новых объектов проверки. Так что, похоже, нет проблем с использованием этого keyPath в предикате, только sortDecriptor.

Документация Apple, однако, говорит об этом; -

Вы не можете установить зависимости для отношений ко многим. Например, предположим, что у вас есть объект Order с отношением ко многим (orderItems) к коллекции объектов OrderItem, а объекты OrderItem имеют атрибут price. Возможно, вы захотите, чтобы у объекта Order был атрибут totalPrice, который зависит от цен всех объектов OrderItem в связи. Вы не можете сделать это, реализовав keyPathsForValuesAffectingValueForKey: и вернув orderItems.price в качестве пути ключа для totalPrice. Вы должны наблюдать за атрибутом price каждого из объектов OrderItem в коллекции orderItems и реагировать на изменения в их значениях, обновляя totalPrice самостоятельно.

Что кажется достаточно ясным, но тогда я не понимаю, почему я могу сделать то же самое в предикате? Это мое первое приложение Core data, поэтому я немного новичок в нем. Я прочитал несколько вопросов по KVO, KVC и т. Д., С которыми я еще не разобрался должным образом. Как видите, все, что я действительно пытаюсь сделать, это отсортировать коллекцию Venues на основе полученного общего количества "hereNow". Может, я ошибаюсь в этом? Если так, был бы признателен за дружелюбное направление в правильном направлении!


person deftangel    schedule 28.05.2011    source источник


Ответы (1)


Вот несколько вещей, которые я могу придумать:

  1. В SortDescriptor нельзя использовать @sum для вычисления значения сортировки. Вы должны рассчитать это где-нибудь еще. Я думаю, поэтому написано «содержащий агрегат KVC». Поскольку вы используете значение «ключа» для создания дескриптора сортировки, оно должно быть фактическим свойством объекта.

  2. Когда у вас есть производное свойство в вашем объекте 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/2EAIEEI179-BA а>

Если вы новичок в CoreData, я бы порекомендовал отличную книгу Маркуса Зарры: https://pragprog.com/titles/mzcd/core-data.

Надеюсь это поможет.

person jschmidt    schedule 16.06.2011
comment
Спасибо, это помогает. Извините, я не принял раньше, был в отъезде. - person deftangel; 26.06.2011