Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

ArtOfWarfare

macrumors G3
Original poster
Nov 26, 2007
9,710
6,304
Update: This post will provides an overview of my problem, but Edit of post #5 by me explains the specific issue I'm having right now.

I have three interrelated entities in a core data model: Correspondents, Subjects, and Messages.

Each and every message has exactly one subject, but each subject may have multiple messages.

Messages may have any number of correspondents and correspondents may have any number of messages.

Subjects may have any number of correspondents and correspondents may have any number of subjects.

I'm starting from the Master-Detail with Core Data template in Xcode. I'd like to make it so that it displays a list of all of the Correspondents with unique Subjects (that is, the Subject has no other Correspondents) as well as all of the Subjects that are shared between Correspondents. I'd like to then sort them all together by their most recent Message (they're all timestamped.)

The issue is that as far as I can tell, a fetchedResultsController should only have a single fetch entity type.

Two possible solutions come to mind:
1 - Make a single superentity that both Correspondents and Subjects inherit from. I can't think of any technical reason why not, but something about it sounds hacky. Or maybe it's just how many headaches I feel like Core Data induces...
2 - Make two fetchedResultsControllers and use both... but then how am I going to manage sorting? Also, something about having two controller classes for a single table view doesn't sound right... it sounds hacky just like #1.

I'm already able to list all of the messages and using the debugger to inspect them suggests that the relationships are being created the way I want them to be.

Which way would people here suggest going about this - is there perhaps another way that someone else has to suggest?
 
Last edited:
One trick is that the SortingKeypath doesn't need to be part of the entity that is user set or ever visible. So the other option is...

Use a Transient Property on the Subject entity (or Message) that prefixes your timeStamp with a hash* of the Sender or Senders. Then if you set yourFetchedResultController to sort by that Transient Property instead of just timeStamp then the results will group by sender or senders then timestamp within Sender group.

*The Hash is just a short string that groups bunch of sender(s) under a single identifier, but it's formula need make the same hash for the same group of sender(s) and also needs to sort so the groups are in the order you want.
 
I tried #1.

It didn't work.

I have a warning that "The inverse relationship for [...] does not reciprocate an inverse"

I have a "Data Model Compiler Error".

It actually crashes if I just try to open the model file.

So... don't do that, evidently. Really bizarre how the graphical user interface let me generate what appears to be a model file that it can't comprehend.

Now I'm back to square 1.

MattInOz, I don't understand your suggestion. How does that cause my fetch to return both Correspondents and Subjects?

I suppose I can give my 2 fetch controller idea a shot... still not certain how I'll go about merging their results into a single array, though...
 
Ok... so...

So as I read it you want a tableView so that a row displays one Subject Entity.
You want the sections of the TableView to divide those subjects in to groups based on which correspondents have written about a subject. Within each of those groups you want it to sort by the time of the message.
Is this correct?

So do you need to fetch more than one entity (Subject)?
If subjects and correspondence are linked then once you have one you have the other.
So why do you need to fetch the second entity (Correspondence)?
When all you really want to do is change the ordering the Subject entity is fetched in based on the Subjects Relationship to the a group of Correspondence entities.
 
Ok... so...

So as I read it you want a tableView so that a row displays one Subject Entity.
You want the sections of the TableView to divide those subjects in to groups based on which correspondents have written about a subject. Within each of those groups you want it to sort by the time of the message.
Is this correct?

So do you need to fetch more than one entity (Subject)?
If subjects and correspondence are linked then once you have one you have the other.
So why do you need to fetch the second entity (Correspondence)?
When all you really want to do is change the ordering the Subject entity is fetched in based on the Subjects Relationship to the a group of Correspondence entities.

Alright, there's a misunderstanding here. Both correspondents and subjects should be mixed together. It's a flat list with just one section. The only thing rows being near each other means is that they have messages that were received around the same time.

If a subject has more than one correspondent, it should be returned.
If a correspondent has a subject that only it belongs to, it should be returned.
These returned subjects and correspondents should all be mixed together and sorted based on when their most recent message was received.

Have I made it clearer this time?

Edit: Okay, I think I almost have exactly what I want using a single entity called "Folder" which has the attributes: hasCorrespondent, hasSubject, and timeStamp. It also has to-one relationships correspondent and subject. These each have to-one inverses. My fetch finds and sorts Folders, but the data that actually gets displayed in the table is from the Subject or Correspondent object that's related to the Folder.

Here's my current problem, I have this fetch request written to look for Folders which contain the relevant entities, but it's not working the way I'd like:

Code:
(hasCorrespondent == 1 AND [b]ANY correspondent.subjects.correspondents.@count == 1[/b]) OR (hasSubject == 1 AND subject.correspondents.@count >= 1)

The bolded portion is the part giving me troubles. I'd like that part to tell me if the correspondent is the only one related to a given subject. But as written, I'm getting this error message:

Code:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported function expression count:(correspondent.subjects.correspondents)

Someone on StackOverflow suggested this change:

Code:
SUBQUERY(correspondent.subjects, $s, $s.correspondents.@count == 1).@count > 0

But now I'm getting a different error:

Code:
'Keypath containing KVC aggregate where there shouldn't be one; failed to handle $s.correspondents.@count'

After googling the causes of this issue, I tried this:

Code:
correspondent.subjects.@count > 0

but that didn't seem to solve anything...

I kind of wish I knew how to go about debugging core data issues like this...
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.