Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
Hey guys. My first time playing with Core data. I've hit a little snag and after reading the docs and tutorials I could find. I'm still stumped.

The problem is that I need to create an instance of an entity whenever an instance of another entity is created.

I have a 'Language' entity which has a relationship to a 'Generator' Entity. The relationship is one to one. The generator uses a custom class that inherits from NSManagedObject (it needs to do some other stuff besides manage data)

In the nib file I have an NSArrayController for the Language entities and an NSController object for the Generator. The NSController gets it's content from a selection binding to the Language NSArrayController.

Now when I create a new language in the NSArrayController I need it to create a new instance of the generator to accompany it.

So i created a custom class for the Language Entity and implemented init like this

Code:
-(id)init
{
       if(self = [super init])
       {
            newGenerator =  [[Generator alloc] init];
            [self setobject:newGenerator forKey:@"generator"];
        }
}

But that doesn't seem to do the trick. When i add a new Language I don't seem to get a new Generator. (i've got other interface elements that access attributes of the generator and i can't add items to them, even though they are connected properly)
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
NSManagedObjects are initialized via initWithEntity:insertIntoManagedObjectContext: - try that instead of just init
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
I'm not at all familiar with Core Data; so I don't know if there's an easier/better way to do what you're doing... but..

Are you sure the init method that NSArrayController is calling is the same one that you've posted above?

Also, the "setobject:forKey:" method, you call it below with a lowercase "O", was that a typo?
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
NSManagedObjects are initialized via initWithEntity:insertIntoManagedObjectContext: - try that instead of just init

Cool I'll give that a shot.

How do i reference the managed object context of the app?

So the generator init should read

newGenerator = [[Generator alloc] initWithEnity:Generator insertIntoManagedObjectContext:xxxxx?]
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
I'm not at all familiar with Core Data; so I don't know if there's an easier/better way to do what you're doing... but..

Are you sure the init method that NSArrayController is calling is the same one that you've posted above?

Also, the "setobject:forKey:" method, you call it below with a lowercase "O", was that a typo?

I'm not sure anymore. I thought it was. But that might be wrong.

And yeh I had setObject :)
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
I was going to suggest you should override the initWithEntity... method (but the documentation suggests you shouldn't) instead of overriding init, it would work.

You could put the code to create the generator in one of the awake... methods, which should work regardless of which init.. method is used.
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
Thanks for the steer guys

I'll have another fiddle when i get home and let you know how i get on.
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
How do i reference the managed object context of the app?

Just how you'd reference any other object in your application. When you create a "Core Data Application" project in Xcode, Apple provides within the project code for creating the managed object context and other Core Data objects. Check it out to see how they do it.
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
NSManagedObjectContext *context=[[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];

is how you get the context in a document based app, it's on the Core Data page on Apples site for a non-document based one.
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
Thanks loads guys.

After re-reading the docs and helped by what you guys wrote here I put this in my LanguageMO class and it seems to have done the trick

Code:
- (void) awakeFromInsert 
{

    [super awakeFromInsert];
	
	// define context and model for current document
	NSManagedObjectModel *model =[[[NSDocumentController sharedDocumentController] currentDocument] managedObjectModel];
	NSManagedObjectContext *context = [[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];

	NSEntityDescription *generatorEntity = [[model entitiesByName] objectForKey:@"Generator"];

	GeneratorMO *newGenerator = [[GeneratorMO alloc] initWithEntity:generatorEntity
					insertIntoManagedObjectContext:context];

	[self setValue:newGenerator forKey:@"generator"];
		
}

Once again, thanks loads guys
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
PS, Why are you subclassing NSManagedObject, there really is little point, I have personally found no need to.
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
PS, Why are you subclassing NSManagedObject, there really is little point, I have personally found no need to.

The generator entity in addition to storing data also needs to have a number of methods to process that data and produce new data from it. I could have had another class do this and just use the generator as a data store, but that seemed really ugly, especially as the methods were so intrinsically linked to the data stored in generator.

The generator stores

- an array of sylable shapes and the frequency of their occurance
- an array of letter categories
- the minimum number of sylables in a word
- the max number of sylables in a word
- the average number of sylables in a word
- the number of words to generate

It then has the following methods.
-generate an array of random words based on the above information
-an inverse normal distribution to work out the required number of sylables in a word.
 

Eraserhead

macrumors G4
Nov 3, 2005
10,434
12,250
UK
The generator entity in addition to storing data also needs to have a number of methods to process that data and produce new data from it. I could have had another class do this and just use the generator as a data store, but that seemed really ugly, especially as the methods were so intrinsically linked to the data stored in generator.

The generator stores
- an array of sylable shapes and the frequency of their occurance
- an array of letter categories
- the minimum number of sylables in a word
- the max number of sylables in a word
- the average number of sylables in a word
- the number of words to generate

It then has the following methods.
-generate an array of random words based on the above information
-an inverse normal distribution to work out the required number of sylables in a word.

Some of these might be better stored in the model itself, it's worth considering as it'd make saving the information quicker.
 

zedLondon

macrumors member
Original poster
Jun 25, 2007
44
0
London
Some of these might be better stored in the model itself, it's worth considering as it'd make saving the information quicker.


All the data elements are stored in the model. The generator entity just uses a subclass of NSManagedObject that provides the inverse normal and generate methods.

I don't provide any accessor methods or storage variables for any of the data elements. I just use the [self valueForKey:mad:"xxx"] approach.
 

whooleytoo

macrumors 604
Aug 2, 2002
6,607
716
Cork, Ireland.
All the data elements are stored in the model. The generator entity just uses a subclass of NSManagedObject that provides the inverse normal and generate methods.

I don't provide any accessor methods or storage variables for any of the data elements. I just use the [self valueForKey:mad:"xxx"] approach.

Using valueForKey: and setValue:forKey: can be a good idea, since they'll first try to use accessors if present, then set the instance variables directly if not (autoreleasing the old value and retaining the new).

So, if you do decide to add accessors later, you don't need to change any code to call them (provided you use the appropriate method naming conventions).
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.