NSSortDescriptor with to-many relationship - core-data

I have a Parent entity which has to-many Child. If I order the Parent fetch with a property (e.g. name), everything works fine. But if I try this:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"child.#count" ascending:NO];
It doesn't work. I've also tried to add
[fetchRequest setRelationshipKeyPathsForPrefetching:[NSArray arrayWithObject:[entityProperties objectForKey:#"child"]]];
But it didn't work as well.
Am I allowed to sort by to-many.#count or do I need to add a property and update it each time I add a child?

Assuming you are using a sqlite store; you cannot sort by #count because it is resolved at the "object" level whereas the NSSortDescriptor on the NSFetchRequest is resolved at the database level. Therefore, as you guessed, you would need to create a counting property to sort by.
If you are using a binary or in-memory store type then count should work fine since they are only accessed as objects.

Related

Method for setting/adding value for relationship

What method will be called by Core Data on NSManagedObject when setting a value for to-one relationship? What method will be called when adding a value to to-many relationship? Thanks.
/Mikael
Maybe you are looking for something like:
Managed Object Accessor Methods - Core Data Programming Guide
Its like this
managedObjectInstance.property = value;
[self.managedObjectContext save:&error];
Ex: if you want to save username in user entity it will be
_userEntity.username = #"Mikeal Hakman";
[self.managedObjectContext save:&error];
One to Many or Many to May always carries NSSet example
_residenceEntity.Seller = [NSSet setWithObjects:seller, nil];
[self.managedObjectContext save:&error];
Obviously I didn't manage to formulate my question clearly enough. I'll try again.
In a subclass of NSManagedObject I need to know when to-many and to-one relationships are being changed. That includes the very first change when the object is being fetched or inserted. I try all the accessors described in https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdAccessorMethods.html to no avail. I can see in my UI that the relationship is there but no accessor methods has been called on my object. Also when I remove the relationship, it goes away in UI but no methods on my object are called. Thanks.
/Mikael

core data fetching and sorting with nil value

I'm facing a problem using Core Data.
In my core data model, I have Grove Entity and Tree Entity, with one-to-many relationship between Grove and Tree, and one to one relationship between Tree and Grove
(each Tree may be in one grove max).
But some Tree may be "wild" and not be part of any Grove.
I'm trying to use a fetResultController to display all my trees in a table view.
Each Grove would be a section of the table view, and the "wild" trees must be in a separate section.
My code is like this:
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Tree" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
// Edit the sort key as appropriate.
NSSortDescriptor *sectionSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Grove.name" ascending:YES];
NSSortDescriptor *rowSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"type" ascending:YES];
NSArray *sortDescriptors = #[sectionSortDescriptor, rowSortDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:#"Grove.name" cacheName:nil];
As you can see I'm fetching all Trees.
The first sort descriptor, used to determine the sections is base on the one-to-one relationship from tree to grove, and looks for the grove name.
The second sort descriptor is used to sort the trees inside a given section, and it sorts them by type.
This code works absolutely fine when the trees have a grove defined.
But the trees with grove=nil are not fetched by this request.
Do you know a way to achieve the wanted behaviour ?
Do I have to create a fake grove for the wild trees ?
I recommend to make a special Grove instance that represents "none", as you suggest.
Anther solution is to fetch the groves and manipulate your table view datasource methods as follows:
Return the number of results +1 as the number of sections. E.g. the last section for the wild trees.
Configure the section header according to the returned grove entity.
Return theGrove.trees.count as the number of rows in a section, make a special fetch for the other trees for the last section.
etc..
You get the gist. It s a bit more complicated and a non-standard use the fetched results controller, but I have sen it work quite well before.

How can I add an object to core data at specific index

What I really want is an persistent ordered list. And after a years learning on xcode had the hubris to tackle Core Data for it.
So I added core data, copied the boiler-plate code and got it working with a single entity and a single attribute... to an extent.
What I would like to do is, at a specific index, insert a new object lower in the pecking order with all the ones above it shifting up a position. Googling seems to point to it being possible since ios5; but there is little code to get my paws on.
Have I missed out something glaringly obvious in setting up my core-data to make it indexable? Adding a NSOrderedSet as a parallel attribute? Or does something like Magic Records do it well with a simple line of code?
Or am I on a hiding to nothing?
Many thanks.
Bee
what you probably want to do is use an existing field to sort your query, or add a field specifically for sorting.
once you have a field to sort on its pretty easy to add a NSSortDescriptor to your fetch request.
something like this should work.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"fieldToSortOn" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];

Knowing what persistent store a query comes from

It's possible what I'm trying to do can't be done with Core Data so, if so, please let me know.
I have a ManagedObjectContext and I'm bringing in sqlite databases by adding them through addPersistentStoreWithType . . .
So I'll add in some number of databases - let's say between 1 and 5 and then I perform fetches on data in the databases. It's great that I don't have to say what sources I'm searching through - results just come back and they're merged together.
However, what if I WANT to know what Store each result came out of? Is that even possible? Am I thinking too "old school" like I want to know what "files" the results were found?
Help / advice would be appreciated.
Here's some code:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"PMBEntity"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:#"Name" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[fetchRequest setReturnsDistinctResults:YES];
[sortDescriptor release];
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
See, above I have a PMBEntity which is a Core Data NSManagedObjectModel I created through XCode. As you can tell, one (of the many) fields is "Name". Here I'm searching for all unique Names and sorting by Name.
What is returned to me is an NSArray of these PMBEntity objects.
You want the persistentStore attribute of the managed object's objectID attribute. That will provide you a URL to the persistent store holding the managed object.
However, that is only after the object has been saved at least once to the persistent store. Prior to that it has a temporary UUID that doesn't point to a store. I'm not sure how it is effected by the new imported stores. Probably gets an permanent ID when read in but I haven't test it yet.
Well, when when you fetch, you have NSManagedObject instances as the result. The NSManagedObject instance has a reference to its NSManagedObjectContext. That NSManagedObjectContext has a reference to its persistentStoreCoordinator. The NSPersistentStoreCoordinator instance has a reference to the persistent store and the NSManagedObjectModel.

more elegant way to compare string attribute for Entities

Dear all.
Currently i need to extract necessary objects from core data but i have just attribute name in entity. TO setup reverse relationship, i find just one way to loop around all objects in managed objects, compare strings for checking necessary attributes accordance and setup relationship. May someone have better way. relationship carrier is part of NamesTranslationRules Entity and connect to Carriers Entity
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:[NSEntityDescription entityForName:#"Carriers"
inManagedObjectContext:moc]];
NSArray *carriers = [moc executeFetchRequest:request
error:&error] ;
for (NSManagedObject *carrier in carriers)
{
if ([[carrier valueForKey:#"name"] isEqualToString:[tempRules valueForKey:#"carrier"]]) [namesTranslationRules setValue:carrier forKey:#"carrier"];
}
A parent object's is create at application startup as carrier's name with some attributes. Later user have to choice a name from another source and based on user's choice we have to add appropriate entity, which have already present parent entity carrier.
What do you mean by a reverse relationship? If the relationship is already bi-directional then the reverse will be set up for you automatically by Core Data.
If you mean something else, you can look at using a predicate on your NSFetchRequest to pre-filter the objects and skip the string comparison.
Update 1
You should know the parent object at the time of the creation and should be connecting them at that time.
Where is the data coming from?

Resources