4
votes

I have a NSManagedObject with the following interface.

@class Organization, Person;

@interface Assistance : NSManagedObject
@property (nonatomic, retain) NSDate * date;
@property (nonatomic, retain) Organization *organization; // Not optional, 1 to 1
@property (nonatomic, retain) NSSet *persons; // 1 to many
@end

Person has a 1-1 relationship with Organization. Assistance has a 1-1 relationship with Organization and a 1-may relationship with Person.

The first time I tried to save an entry it works perfectly, but not the second time.

Case scenario: I add an entity with date 2013-07-26 00:00:00 +0000, its respective organization and person(s).

I restart the app. It performs a search for the current date (7/27) and it doesn't find anything. I start editing stuff on the app, so it creates a new entity with MagicalRecord's convenience method [Assistance createEntity]; I immediately set the date (7/27) and the organization. The Person objects are added or removed. When another date is selected, I try to save the current Assistance object entity, for this I have implemented the setCurrentDate method myself:

- (void)setCurrentDate:(NSDate *)currentDate
{
    if (assistanceWasChanged) {
        NSLog(@"> > > Has changed, need to save with Persons {%i}, org {%@}, date {%@}", [self.assistance.persons count], self.organization.name, self.currentDate);
//        [[NSManagedObjectContext defaultContext] saveOnlySelfWithCompletion:^(BOOL success, NSError *error) { NSLog(@"> > > 01:Assistance saved?"); }];
        [[NSManagedObjectContext defaultContext] saveOnlySelfAndWait];
    }
    assistanceWasChanged = NO;
    _currentDate = currentDate;
    [self setCurrentAssistance]; // Tries to find Assistance with new date
}

But this time, it won't save. I get a Cocoa error 1570 (not all of the required fields are filled):

> > > Has changed, need to save with Persons {1}, org {MSF}, date {2013-07-27 00:00:00 +0000}
2013-07-27 20:23:41.017 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8d61e50) → Saving <NSManagedObjectContext (0x8d61e50): *** DEFAULT ***> on *** MAIN THREAD ***
2013-07-27 20:23:41.018 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8d61e50) → Save Parents? 0
2013-07-27 20:23:41.018 -[NSManagedObjectContext(MagicalSaves) MR_saveWithOptions:completion:](0x8d61e50) → Save Synchronously? 1
2013-07-27 20:23:41.018 -[NSManagedObjectContext(MagicalRecord) MR_contextWillSave:](0x8d61e50) Context DEFAULT is about to save. Obtaining permanent IDs for new 1 inserted objects
2013-07-27 20:23:41.019 CoreData: sql: BEGIN EXCLUSIVE
2013-07-27 20:23:41.019 CoreData: sql: SELECT Z_MAX FROM Z_PRIMARYKEY WHERE Z_ENT = ?
CoreData: sql: UPDATE Z_PRIMARYKEY SET Z_MAX = ? WHERE Z_ENT = ? AND Z_MAX = ?
2013-07-27 20:23:41.020 CoreData: sql: COMMIT
2013-07-27 20:23:41.021 +[MagicalRecord(ErrorHandling) defaultErrorHandler:](0x6b3a0) Error: <Assistance: 0x9cb16c0> (entity: Assistance; id: 0x9e5ac00 <x-coredata://15A3-4C6D-4025-9131-3D51048/Assistance/p1> ; data: {
    date = "2013-07-26 00:00:00 +0000";
    organization = nil;
    persons = "<relationship fault: 0x8d80500 'persons'>";
})

At no point in time is organization nil. Also, object with date '2013-07-26' was never fetched/edited. The new object I'm trying to add has date '2013-07-27', as my log statement shows. At first I thought CoreData has a pointer to old data, but that's not the case, the first-inserted date was never fetched. (When I restart the app, the first object (7/26) is still there. In case it makes a difference, the Assistance entity object is a property in my implementation file:

@property (strong, nonatomic) Assistance *assistance;

Am I missing something about Core Data? Why is the first-inserted object being accessed when saving a new entity object? and why is organization nil?

1
Maybe show the code where you create the new object, including the part where you set the organization?ophychius
There are many other places where things could go wrong. The main problem here is that I'm not sure you understand the idea of contexts yet. Objects are tied to a context, and you need to save the context in order for data to persist, which will then allow you to search for it later. I'm not seeing anything "wrong" in this code, but I'm also feeling like I don't have the whole picture to pinpoint the problem either.casademora
@casademora Thanks Saul! I'd like to believe I understand the idea of contexts, but I'll give it a look one more time. My problem was that 2 of my 3 entities had the wrong relationship multiplicity.Eric

1 Answers

8
votes

It looks like you aren't creating a new organisation. Instead you're linking the new Assistance object to the existing organisation. Because the relationship is 1 to 1 that means that the old Assistance object has its relationship to the organisation broken. This is done automatically by Core Data to maintain the integrity of the configuration you have set.

So, either create a new organisation object or change the relationship multiplicity.