CocoaDev

Edit AllPages

I’m changing a non document based application to use core data, to gain some of core data’s freebie advantages. I appear to have got the core data part working okay.

The Entity Graph looks like this.

Genome —1 to N—> General/XForms —1 to N–> Variations

The data is build the hard way as the app is designed to be compatible with another application’s file format. So for example…

genomeEntity = General/[NSEntityDescription insertNewObjectForEntityForName:@"Genome" inManagedObjectContext:moc];
....

xFormSet = General/[[NSMutableSet alloc] initWithCapacity:numberOfXForms];
for(i=0; i<numberOfXForms;i++) {
	xFormEntity = General/[NSEntityDescription insertNewObjectForEntityForName:@"General/XForm" inManagedObjectContext:moc];
	[xFormSet addObject:xFormEntity];	
          ...
         /* similar loop for variations */
   }
[genomeEntity setValue:xFormSet forKey:@"xforms"];

Which is how I interpret ‘Manipulating Relationships’ in the core data guide. I can add my data into a General/NSManagedObjectContext and get it back out again, so I guess that is fairly correct.

I’ve bound an General/NSArrayController to my managedObjectContext, with attributes set to the Genome entity. I’ve got an General/NSTableView with Columns bound to two of the Genome attributes via the General/NSArrayController arrangedObjects controller key.

When I run my Application I get a row in the table for each Variation entity in the context. If I comment out the addition of the variations code I get one for each General/XForm entity, and if I comment out the General/XForm code I get what I was expecting in the first place, one level for each Genome Entity.

So How do I get just one row in the table for the top level entity without getting rid of all my code or is that just the way things are supposed to work ?


This is not going to help you much, but at least, I know one thing for sure: you should have only 2 rows, one per Genome, if things are done properly, no matter how many 1–N relationships the entity has. I am not sure where you should look first, the code you give looks good. Maybe you can build a small test case for which you can show all the code? In which methods are the xForms added (e..g in awakeFromInsert?)? Also, check your model: does any of your entity use a subclass of General/NSManagedObject for extra methods? Finally, be more descriptive about the nib setup.


As the code is GPL I’ve put a vastly cut down copy available at http://oxidizer.sf.net/oxidizer_core.zip I weighs in at a touch under 3MB. All the following describes the cut down project….

The nib is as I described it above.

I have an object, General/FractalFlameModel, with an General/NSManagedObjectContext public variable ‘moc’. The persistent store is an in memory store. created in General/FractalFlameModel’s init method. I’ve bound an General/NSArrayController’ managedObjectContext binding to ‘moc’, with attributes set to Entity, Genome. I’ve got an General/NSTableView with the Columns value binding bound to two of the Genome attributes via the General/NSArrayController arrangedObjects controller key. There’s a controller class to that now does not do much controlling. And two windows, oxidizer, the main window and preferences which I would get rid of but can not delete for some reason.

The code that is used to populate the context is below createGenomeEntityFrom:withImage:inContext: is called in a loop from the model class. The Genome class is a factory class hence the class methods. …

@implementation Genome

The only custom managed object is for the Genome Entity, it holds an General/NSColor, General/NSImage and General/NSAttributedString hence is has the standard code to store transients in binary persistant attributes.

@implementation General/GenomeManagedObject

}

}

}

}

@end

If I run the following code I get TEN entities, which matched the number of rows, returned, The extra enties are General/XForms, I’m beginning to think that insertNewObjectForEntityForName:inManagedObjectContext is the root of my problem.

General/NSArray *genomes;

General/NSPredicate * predicate;                        
General/NSFetchRequest *fetch = General/[[NSFetchRequest alloc] init];
[fetch setEntity:General/[NSEntityDescription entityForName:@"Genome" inManagedObjectContext:moc]];
genomes = [moc executeFetchRequest:fetch error:nil];
[fetch release];

The code is in an action tied to the Render button in the cut down app, you’ll need to run in Debug as there’s no print code.


Replying to myself here… I brought the above code up on the cocoa-dev list and appearently this is the expected behaviour for ‘sub-entites’. Since I had no idea what a ‘sub-entity’ was with regards to core data or how I even made one I had to google around. Reading between the lines it appears to have something to do setting the parent entity setting. I’ve have to look into this to comfirm it has I’m away from my Mac and have no recollection of using the Parent: drop down.