Question

Does anyone know how to do a nested sort (not sure if that's the best term for it) using NSSortDescriptors?

I'm using NSSortDescriptors to fetch NSManagedObjects.

I have a NSManagedObject called Conversation that has a one-to-many relationship to Messages. Each Conversation has a NSSet of Messages.

Each Message has a timeReceived Date property. I'm trying to sort my Conversations by their respective latest Message's timeReceiveds

To restate: I'm trying to find the Message with the last timeReceived in each Conversation, then sort the Conversations by their respective latest Messages. Messages and Conversations are NSManagedObjects.

The Key string nature of these descriptors has made it really hard for me to figure out.

I saw something on SO that suggested something like: NSSortDescriptor * sortByDate = [NSSortDescriptor sortDescriptorWithKey:@"messages.@min.timeReceived" ascending:NO];

But I just get a crash:

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Keypath containing KVC aggregate where there shouldn't be one; failed to handle messages.@max.timeReceived'

Have any of you done something like this before?

- (NSFetchedResultsController *) fetchSortedConversations
{
    NSSortDescriptor *sortByDate = [NSSortDescriptor sortDescriptorWithKey:@"latestMessage.timeReceived" ascending:NO];

    // I implemented a workaround where I set a latestMessage for each Conversation somewhere else, but I'd like to be able to sort the Conversations without having to manually manage the latest message.

    NSArray * sortDescriptors = @[sortByDate];

    NSFetchedResultsController * conversations = [self.coreDataManager fetchEntitiesWithName: NSStringFromClass([Conversation class]) sortDescriptors:sortDescriptors sectionNameKeyPath:nil predicate:nil];


    return conversations;
}
Was it helpful?

Solution

I would assume the problem you're facing can't be solved with NSFetchedResultsController as currently formulated, because it can't really be solved neatly in SQL. So NSFetchRequest probably just declines to do it, and that bubbles upward.

The easiest solution would be to implement - willSave on the managed object subclass you've got for Conversation and in that find @max.timeReceived and store it to a property directly in Conversation. Then tell your fetched results controller to sort on that.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top