Search code examples
objective-cxcodecore-datafetched-property

How do I create an NSFetchedPropertyDescription programmatically?


I have a pre-existing NSManagedObjectModel that I created with the Xcode GUI. I want to create a sorted fetched property, which Xcode 3.2's GUI doesn't support. I do all of this before creating my NSPersistentStoreCoordinator because I know you can't modify a NSManagedObjectModel after an object graph manager has started using it. I created the NSFetchedPropertyDescription thusly:

NSManagedObjectModel *managedObjectModel = ... // fetch from my mainBundle

NSEntityDescription *fetchedPropertyEntityDescription = [entitiesByName objectForKey:@"MyEntity"];

NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
[fetchRequest setEntity:fetchedPropertyEntityDescription];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"myPredicateProperty == $FETCH_SOURCE"]];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"mySortProperty" ascending:YES]]];

NSFetchedPropertyDescription *fetchedPropertyDescription = [[[NSFetchedPropertyDescription alloc] init] autorelease];
[fetchedPropertyDescription setFetchRequest:fetchRequest];
[fetchedPropertyDescription setName:@"myFetchedProperty"];

NSEntityDescription *entityDescription = [entitiesByName objectForKey:@"MyFetchSourceEntity"];

[entityDescription setProperties:[[entityDescription properties] arrayByAddingObject:fetchedPropertyDescription]];

When I call

[fetchedPropertyDescription setFetchRequest:fetchRequest];

I get the following exception:

NSInvalidArgumentException: Can't use fetch request with fetched property description (entity model mismatch).

Solution

  • I needed to add the NSFetchedPropertyDescription to the NSEntityDescription before setting the NSFetchRequest on the NSFetchedPropertyDescription.

    The proper steps are below:

    NSManagedObjectModel *managedObjectModel = ... // fetch from my mainBundle
    
    NSEntityDescription *fetchedPropertyEntityDescription = [entitiesByName objectForKey:@"MyEntity"];
    
    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
    [fetchRequest setEntity:fetchedPropertyEntityDescription];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"myPredicateProperty == $FETCH_SOURCE"]];
    [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"mySortProperty" ascending:YES]]];
    
    NSFetchedPropertyDescription *fetchedPropertyDescription = [[[NSFetchedPropertyDescription alloc] init] autorelease];
    //DON'T DO THIS HERE, AN ERROR WILL OCCUR
    //[fetchedPropertyDescription setFetchRequest:fetchRequest];
    //
    [fetchedPropertyDescription setName:@"myFetchedProperty"];
    
    NSEntityDescription *entityDescription = [entitiesByName objectForKey:@"MyFetchSourceEntity"];
    
    [entityDescription setProperties:[[entityDescription properties] arrayByAddingObject:fetchedPropertyDescription]];
    
    //DO THIS HERE INSTEAD
    [fetchedPropertyDescription setFetchRequest:fetchRequest];