Combo Core Data Fetch? (Update: Unsupported function expression count)!?

Discussion in 'iOS Programming' started by ArtOfWarfare, Jun 30, 2013.

  1. ArtOfWarfare, Jun 30, 2013
    Last edited: Jul 7, 2013

    ArtOfWarfare macrumors G3


    Nov 26, 2007
    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?
  2. MattInOz macrumors 68030


    Jan 19, 2006
    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.
  3. ArtOfWarfare thread starter macrumors G3


    Nov 26, 2007
    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...
  4. MattInOz macrumors 68030


    Jan 19, 2006
    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.
  5. ArtOfWarfare, Jul 6, 2013
    Last edited: Jul 8, 2013

    ArtOfWarfare thread starter macrumors G3


    Nov 26, 2007
    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:

    (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:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unsupported function expression count:(correspondent.subjects.correspondents)
    Someone on StackOverflow suggested this change:

    SUBQUERY(correspondent.subjects, $s, $s.correspondents.@count == 1).@count > 0
    But now I'm getting a different error:

    '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:

    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...
  6. MattInOz macrumors 68030


    Jan 19, 2006
    Can't say this is an issue I've hit int he past.

Share This Page