Clifton Labrum
Clifton Labrum

Reputation: 14060

How to Save Entity with Relationship in Core Data

I'm new to Core Data, so go easy on me. :) I'm currently using iOS 7 in Xcode 5.

I have two Entities: Aircraft and Entry. There is a one aircraft to many entry relationship.

I'm trying to save a new Entry which has an aircraft object in it. Here is my Entry.h file (minus the #import):

//  Entry.h
@class Aircraft;

@interface Entry : NSManagedObject
  @property (nonatomic, retain) NSNumber *duration;
  @property (nonatomic, retain) NSDate *flightDate;
  @property (nonatomic, retain) Aircraft *aircraft;
@end

Meanwhile, over in my view controller where I save the new Entry, I have the following code. I use a dictionary to set up my data prior to creating a new record:

//Add New Entry
Aircraft *aircraft = [Aircraft new];
aircraft.aircraftRegistration = _aircraftRegistrationTextField.text;

NSDictionary *newEntry = @{
  @"aircraft": aircraft, //???
  @"flightDate": [formatter dateFromString:_flightDateTextField.text],
  @"duration": [PPHelpers convertHHMMtoDecimal:_durationTextField.text],
};

//Save new Entry to Core Data
PPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];

NSManagedObject *item = [NSEntityDescription insertNewObjectForEntityForName:@"Entry" inManagedObjectContext:context];

[item setValuesForKeysWithDictionary:newEntry];

NSError *error;
[context save:&error];

I get a couple errors from this:

CoreData: error: Failed to call designated initializer on NSManagedObject class 'Aircraft'

and...

-[Aircraft setAircraftRegistration:]: unrecognized selector sent to instance 0x110b0b550

I suspect the issue is that I'm not adding the Aircraft to the Entry in the right way.

Any ideas what I'm doing wrong?

Upvotes: 3

Views: 2373

Answers (2)

tdelepine
tdelepine

Reputation: 2016

if Aircraft is an parent relation entity, you need to use instanciate it by insertNewObjectForEntityForName it's the same that Entry.

//Save new Entry to Core Data
PPAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];



//Add New aircraft
Aircraft* aircraft = (Aircraft*) [NSEntityDescription insertNewObjectForEntityForName:[NSClassFromString(Aircraf) inManagedObjectContext:context];
aircraft.aircraftRegistration = _aircraftRegistrationTextField.text;


Entry* item = (Entry*) [NSEntityDescription insertNewObjectForEntityForName:NSClassFromString(Entry) inManagedObjectContext:context];

[item setAircraft:aircraft];
[item setFlightDate:[formatter dateFromString:_flightDateTextField.text]];
[item setDuration:[PPHelpers convertHHMMtoDecimal:_durationTextField.text]];


NSError *error;
[context save:&error];

Upvotes: 1

Martin R
Martin R

Reputation: 539685

Aircraft *aircraft = [Aircraft new];

creates an object without calling the designated initializer. You should replace it by

Aircraft *aircraft = [NSEntityDescription insertNewObjectForEntityForName:@"Aircraft" inManagedObjectContext:context];

Note: It is possible to set Core Data attributes with setValuesForKeysWithDictionary, but a more direct, type-safe and less error-prone way would be to use the Core Data accessors:

Entry *entry = [NSEntityDescription insertNewObjectForEntityForName:@"Entry" inManagedObjectContext:context];
entry.aircraft = aircraft; // from above
entry.duration = ...;
entry.flightData = ...;

Upvotes: 4

Related Questions