0
votes

I have a problem regarding core data. I have an app with multiple tabs. Every tab holds a list of different "objects". In each tab i have an add button (+) that takes me to a screen where i can add an "object".

The problem :

When i click add an entity for insert is being created and added to the context.

So, i go on first tab, click add - an entity is in context. I go on other tab, i click add - another entity is in context.

I finish adding information for one of them ( to be valid ) and hit save. Now core data throws an exception saying that could not save the context because the other entity it's not valid.

One idea that came into my mind was :

Copy all objects that are invalid from context, save the context, add the copied ones back (and so on when needed).

But an entity could have other relations with other entities so Person could have address, role, Contact Details.. and Company could have Address, Employes .. etc. If person is invalid and has relationship Address valid , above idea fails because will not save person but will save address , what it's not correctly.

Something with a temporarily context could work but i don't have an clear idea how to implement this.

Another idea is to take all relationships for an entity (eg Person) when i want to save it, and save only Person. But i failed to implement an recursive function ( the problem lays in the fact that relationships are inverse and because of many many relationships on my coredata model (person has contact details and also company) ).

Here is the code :


    - (void)relationshipInstancesForManagedObject:(NSManagedObject *)managedObject 
                                        andSkipValue:(id)skipValue 
                                              andSet:(NSMutableSet *)set
    {
        for (NSRelationshipDescription *relationship in managedObject.entity.properties)
        {
            if (![relationship isKindOfClass:[NSRelationshipDescription class]]) continue; 
            id value = [managedObject valueForKey:relationship.name];
            if (value == skipValue || value == nil || value == self  || [set containsObject:value] ) continue;
            NSLog(@"%@",value);
            if (relationship.isToMany)
            {
                if ([value containsObject:skipValue] || [value containsObject:managedObject] || [value count] == 0 ) {
                    continue;
                }
                for (NSManagedObject *entity in value)
                {
                    [set addObject:entity];
                    [self relationshipInstancesForManagedObject:entity 
                                                   andSkipValue:skipValue 
                                                         andSet:set];
                }           
            } else {
                if (value != nil) {
                    [set addObject:value];
                    [self relationshipInstancesForManagedObject:value 
                                               andSkipValue:skipValue 
                                                     andSet:set];
                }
            }      
        }
    }

If you have any ideas, I would be grateful.

1
Try not to confuse entities with objects. Like a class, an entity describes a particular type of managed object -- all the objects for a given entity will have the same set of properties.Caleb

1 Answers

1
votes

The simplest solution to your problem is to make sure that all objects are valid when you add them to the store. Collect the information you need to create a valid object first, and only then add a new object along with all the required information.

Also, consider carefully whether you need to require all the properties that you currently do. If you have two entities that each have a relationship to the other, do you need to require both relationships? Could you make one of the relationships optional? That can help you avoid a chicken and egg problem where it's impossible to add objects for either entity because none of the other type exist yet.