How do I create an NSFetchedPropertyDescription pr

2019-08-08 16:48发布

问题:

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).

回答1:

You can't alter a managed object model once it has been used to create an object graph i.e. after there is context or a store that uses it. The model defines the properties and relationships of all the objects in the graph. If you change it on the fly the graph turns into gibberish.

This applies to fetched properties as well. From the NSFetchProperyDescription docs:

Fetched Property descriptions are editable until they are used by an object graph manager. This allows you to create or modify them dynamically. However, once a description is used (when the managed object model to which it belongs is associated with a persistent store coordinator), it must not (indeed cannot) be changed. This is enforced at runtime: any attempt to mutate a model or any of its subjects after the model is associated with a persistent store coordinator causes an exception to be thrown. If you need to modify a model that is in use, create a copy, modify the copy, and then discard the objects with the old model.



回答2:

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];