Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data Entity Relationship Does Not Save Between Launches

I am writing an application that has four main entities that are all linked via relationships. Some are one to one, some are one to many. Upon initial load, three of the entities load their data from XML files stored locally to the application and one of the entities downloads an XML from the web and loads its data from it. When the app loads it performs a check to see if the data from each of these files is more recent than what it currently has and, if so, it will replace all current data in that entity with data from the appropriate file.

As part of my debug process during writing I have been forcing a delete of all data. When the delete function is called and all data is loaded at app launch the application runs beautifully and all entities and relationships behave exactly as they should. However, when I remove the call to the delete function and it performs the checks and tries to run from data it has stored, all of the relationships seem to disappear. In debugging this, I have found that all of the entities do contain all of the regular data that they are supposed to, they just don't have the relationships anymore. I can't figure out why in the world the relationships are saved on first load but don't retain when all data is not re-imported.

I would imagine some code would be helpful to anyone debugging, however, I'm not sure how much I should include. So, I will start by including just one of the methods called in the data loading class. If anything else would help, please let me know. Any help is very much appreciated.

UPDATED CODE: 2/25/11 (Based on Suggestions - Problem still exists) UPDATED CODE: 2/25/11 - Problem Solved

- (NSArray *) loadFeatures {

    if ([self checkForUpdate:@"Features"]) {

        [self deleteAllObjects:@"Features"];

        NSString *filePath = [self dataFilePath:FALSE withResourceName:@"Features"];
        NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSError *error;
        GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];

        NSArray *featureElements = [doc.rootElement elementsForName:@"FEATURE"];
        NSMutableSet *featureSections = [[NSMutableSet alloc] init];

        for (GDataXMLElement *featureElement in featureElements) {

            NSString *featureName = nil;
            NSNumber *featureSecure = nil;
            NSNumber *featureID = nil;
            NSNumber *featureSortKey = nil;
            DisplayTypes *featureDisplayType = nil;

            NSArray *names = [featureElement elementsForName:@"NAME"];
            if (names.count > 0) {
                GDataXMLElement *firstName = (GDataXMLElement *) [names objectAtIndex:0];
                featureName = firstName.stringValue;
            } else continue;

            NSArray *secures = [featureElement elementsForName:@"SECURE"];
            if (secures.count > 0) {
                GDataXMLElement *firstSecure = (GDataXMLElement *) [secures objectAtIndex:0];
                featureSecure = [NSNumber numberWithInt:firstSecure.stringValue.intValue];
            } else continue;

            NSArray *featureIDs = [featureElement elementsForName:@"FEATUREID"];
            if (featureIDs.count > 0) {
                GDataXMLElement *firstFeatureID = (GDataXMLElement *) [featureIDs objectAtIndex:0];
                featureID = [NSNumber numberWithInt:firstFeatureID.stringValue.intValue];
            }

            NSArray *featureSortKeys = [featureElement elementsForName:@"SORTKEY"];
            if (featureSortKeys.count > 0) {
                GDataXMLElement *firstSortKey = (GDataXMLElement *) [featureSortKeys objectAtIndex:0];
                featureSortKey = [NSNumber numberWithInt:firstSortKey.stringValue.intValue];
            }

            NSArray *featureDisplays = [featureElement elementsForName:@"DISPLAYTYPEID"];
            if (featureDisplays.count > 0) {
                GDataXMLElement *firstFeatureDisplay = (GDataXMLElement *) [featureDisplays objectAtIndex:0];

                for (DisplayTypes *thisDisplayType in self.displayTypes) {
                    if (thisDisplayType.displayTypeID == [NSNumber numberWithInt:firstFeatureDisplay.stringValue.intValue]) {
                        featureDisplayType = thisDisplayType;
                    }
                }
            }

            NSArray *sectionElements = [featureElement elementsForName:@"SECTIONS"];


            for (GDataXMLElement *sectionElement in sectionElements) {

                NSArray *sectionIDs = [sectionElement elementsForName:@"SECTION"];

                for (GDataXMLElement *sectionID in sectionIDs) {
                    NSArray *thisSectionIDs = [sectionID elementsForName:@"SECTIONID"];
                    if ([thisSectionIDs count]) {
                        GDataXMLElement *thisSectionID = (GDataXMLElement *) [thisSectionIDs objectAtIndex:0];

                        for (Sections *thisSection in self.sections) {

                            if ([thisSection.sectionID isEqualToNumber:[NSNumber numberWithInt:thisSectionID.stringValue.intValue]]) {
                                [featureSections addObject:thisSection];
                            }

                        }
                    }
                }
            }


            NSManagedObjectContext *context = [self managedObjectContext];
            NSManagedObject *featureInfo = [NSEntityDescription insertNewObjectForEntityForName:@"Features" inManagedObjectContext:context];
            [featureInfo setValue:featureName forKey:@"name"];
            [featureInfo setValue:featureSecure forKey:@"secure"];
            [featureInfo setValue:featureID forKey:@"featureID"];
            [featureInfo setValue:featureSortKey forKey:@"sortKey"];
            [featureInfo setValue:featureDisplayType forKey:@"display"];
            [[featureInfo mutableSetValueForKey:@"section"] unionSet:featureSections];

            NSError *error;
            if (![context save:&error]) {
                NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
            }

            [[self.managedObjectContext objectWithID:featureDisplayType.objectID] addFeatureObject:featureInfo];
            [self.managedObjectContext save:&error];

            [featureSections removeAllObjects];


        }

        [xmlData release];
        [doc release];
        [featureSections release];

    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Features" inManagedObjectContext:[self managedObjectContext]];
    [fetchRequest setEntity:entity];

    NSError *error;
    NSArray *featureArray = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

    [fetchRequest release];

    return featureArray;

}

UPDATE: 5/25/2011

Per request I am posting a couple of screen shots.

1) This is what I get when the app loads after all data has been deleted and the relationships are in tact

Data Loaded Properly

2) This is what I get when the app runs again without first deleting and reloading data. The tabs at the bottom are created by one of the entities, and are titled a bit different. This happens because the relationship with the DisplayType is not present and it doesn't know what type of view controller to load and it doesn't know which icon to use for the tab.

Data Loaded - Relationships Missing

like image 539
Carl Avatar asked May 24 '11 15:05

Carl


1 Answers

Typically, you wouldn't need to explicitly set both sides of a relationship. When you're dealing with a to-many relationship, it's probably safer to add one entity at a time to the collection, instead of setting the collection all at once. So, instead of:

[featureInfo setValue:[NSSet setWithSet:featureSections] forKey:@"section"];

I would loop through the featureSections Set and add each object one by one to the section relationship of the Feature entity, e.g.:

for (Sections *aSection in featureSections) {
    // use the automatically-generated relationship mutator         
    [featureInfo addSectionsObject:aSection];
}

I hope this helps...

Otherwise, this section in the Apple documentation might be of interest.

like image 154
octy Avatar answered Nov 17 '22 14:11

octy