问题
In my core data model, a Person
has one or more Cars
, specified by the unordered to-many relationship 'Cars'. Frequently, I need to retrieve a Person's cars ordered by datePurchased
, or by dateLastUsed
.
Until now, I have been adding my own method to Person
for carsByDatePurchased
. This uses a sort descriptor to sort the NSSet cars
and return an NSArray.
Could/should I instead use a Fetched Property for this? I am experiencing some performance overhead using the sort descriptor every time I need the cars in a certain order, even going so far as implementing my own caching of carsByDatePurchased
. It looks like the fetched property is cached for me - is that correct?
What are the limitations of a fetched property vs my own implementation?
And crucially, does the fetched property's value persist between executions? If I update the fetched property and save my context, is the value stored for the next time I launch the application?
回答1:
A fetched property will work, and indeed I used it in my own project with a Post->Comment relationship which needs to be sorted by 'date added index'.
There are a number of caveats: You cannot specify a sort descriptor in the visual editor and have to specify it in code.
I use something like this
// Find the fetched properties, and make them sorted...
for (NSEntityDescription *entity in [_managedObjectModel entities])
{
for (NSPropertyDescription *property in [entity properties])
{
if ([property isKindOfClass:[NSFetchedPropertyDescription class]])
{
NSFetchedPropertyDescription *fetchedProperty = (NSFetchedPropertyDescription *)property;
NSFetchRequest *fetchRequest = [fetchedProperty fetchRequest];
// Only sort by name if the destination entity actually has a "index" field
if ([[[[fetchRequest entity] propertiesByName] allKeys] containsObject:@"index"])
{
NSSortDescriptor *sortByName = [[NSSortDescriptor alloc] initWithKey:@"index"
ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortByName]];
}
}
}
}
In My Post entity I have a fetched property called "sortedComments" which is defined as:
post == $FETCH_SOURCE
where posts have a to-many "comments" relationship and comments have a "post" inverse
In opposition to the other answers here: The benefits of using a fetched property like this, is CoreData takes care of the caching and invalidating the cache as comments for a post or indeed the post that owns them changes.
回答2:
If you want to gain some performance, do your fetch with an NSFetchedResultsController and have it working with a cache. Next time you perform the same fetch, the fetch will be faster. In your particular name, you will have to cache names. Take a look at the NSFetchedResultsController documentation.
回答3:
A fetched property is basically a fetch request. I am not aware of ways to add sort descriptors to these properties in the GUI, but I may be wrong. But why not just create a fetch request in your carsByDatePurchased
method and provide a sort descriptor? It returns an array or the results (which you can wrap cheaply in an NSOrderedSet
with copyItems:
flag set to no).
回答4:
AppDelegate *delegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [delegate managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"DataRecord" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSError *error;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
for (NSManagedObject *obj in fetchedObjects) {
NSLog(@"Name: %@", [obj valueForKey:@"name"]);
NSLog(@"Info: %@", [obj valueForKey:@"info"]);
NSLog(@"Number: %@", [obj valueForKey:@"number"]);
NSLog(@"Create Date: %@", [obj valueForKey:@"createDate"]);
NSLog(@"Last Update: %@", [obj valueForKey:@"updateDate"]);
}
NSManagedObject *obj = [fetchedObjects objectAtIndex:0];
[self displayManagedObject:obj];
selectedObject = obj;
来源:https://stackoverflow.com/questions/13016624/fetched-property-in-core-data