Ios – How to use Coredata ordered relationships with NSFetchedResultsController

core-dataiosnspredicate

  1. I have an Items Entity and a Tags Entity.
  2. Items can have multiple Tags and Tags can be linked to multiple Items (many to many
    relationship).
  3. The relationship is an "Ordered Relationship" (using Ordered relationship in IOS5) both ways.

I want to fetch all Items for a Tag using a NSFetchedResultsController.

Queries:

  1. Is it even possible to use ordered relationships with NSFetchRequest and NSFetchedResultsController?
  2. How do I specify the "Sort Descriptor"?
  3. I tried two predicates. The first did not give any results, the second one did give results. Why does the first one does not work? Again how do I specify the sort descriptor to use the sorted order managed automatically by CoreData for this relationship?

Did not work: [NSPredicate predicateWithFormat:@"ANY tags == %@", yyy];

Worked: But less efficient: [NSPredicate predicateWithFormat:@"ANY tags.tagID == %@", xxx];

Best Answer

1 - Yes. It is possible. When you create your mapping file, make sure you change the relationship's type from an NSSet to an NSArray, like so:

    @class Tags

    @interface Entity : NSManagedObject
    ...
    @property (nonatomic, retain) NSOrderedSet *tags;
    ...
    @end

    @interface Entity (CoreDataGeneratedAccessors)
    ...
    - (void)addEntityTags:(NSOrderedSet *)values;
    - (void)removeEntityTags:(NSOrderedSet *)values;
    ...
    @end

Change to:

    @class Tags

    @interface Entity : NSManagedObject
    ...
    @property (nonatomic, retain) NSArray *tags;
    ...
    @end

    @interface Entity (CoreDataGeneratedAccessors)
    ...
    - (void)addEntityTags:(NSArray *)values;
    - (void)removeEntityTags:(NSArray *)values;
    ...
    @end

2 - You can specify a sort descriptor when creating your fetch request, like so:

    NSFetchRequest *fetchRequest [NSFetchRequest new];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Entity" inManagedObjectContext:myManagedObjectContext];

    [fetchRequest.setEntity: entity];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"tags" ascending:<YES|NO>]];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"ANY tags == %@", yyy]];

    NSFetchResultsController *myFetchResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:myManagedObjectContext setcionNameKeyPath:nil cacheName:nil];
    myFetchResultsController.delegate = self;

    [fetchRequest release]; // Forget that if using ARC.

    NSError *error = nil;

    if (![myFetchResultsController performFetch:&error]) {
        NSLog(@"Failed to fetch data: %@", error);
    }

3 - If you use the property, you shouldn't need to specify a predicate for your tags. If you want to further sort your tags, you can simply use a sort descriptor on that array, like this:

    NSSortDescriptor *tagDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"<tags field to sort on>" ascending:<YES|NO>];
    NSArray *sortedTags = [tagsProperty sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptors]];

You can simply read from that property for your tags.

Hope this helps!

Related Topic