核心数据实体关系不会在启动之间保存

时间:2011-05-24 15:04:32

标签: iphone objective-c cocoa-touch ios core-data

我正在编写一个包含四个主要实体的应用程序,这些实体都通过关系链接。有些是一对一的,有些是一对一的。在初始加载时,三个实体将其数据从本地存储的XML文件加载到应用程序,其中一个实体从Web下载XML并从中加载数据。当应用程序加载时,它会执行检查以查看每个文件中的数据是否比当前文件更新,如果是,它将使用相应文件中的数据替换该实体中的所有当前数据。

作为编写过程中调试过程的一部分,我一直在强制删除所有数据。调用delete函数并在应用程序启动时加载所有数据时,应用程序运行得非常漂亮,所有实体和关系的行为都应该完全正常。但是,当我删除对delete函数的调用并执行检查并尝试从它存储的数据运行时,所有关系似乎都消失了。在调试中,我发现所有实体都包含它们应该具有的所有常规数据,它们只是没有关系。我无法弄清楚为什么世界上的关系在第一次加载时保存但在没有重新导入所有数据时都不会保留。

我认为一些代码对任何调试都有帮助,但是,我不确定我应该包括多少。因此,我将首先介绍数据加载类中调用的一个方法。如果有任何其他方法有帮助,请告诉我。非常感谢任何帮助。

更新代码:2011年2月25日(基于建议 - 问题仍然存在) 更新的代码:2/25/11 - 解决问题

- (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;

}

更新:2011年5月25日

根据请求我发布了几个屏幕截图。

1)这是我删除所有数据并且关系完好后加载应用时的结果

Data Loaded Properly

2)这是我在没有先删除和重新加载数据的情况下再次运行时获得的内容。底部的选项卡由其中一个实体创建,标题略有不同。发生这种情况是因为与DisplayType的关系不存在,并且它不知道要加载哪种类型的视图控制器,并且它不知道用于选项卡的图标。

Data Loaded - Relationships Missing

1 个答案:

答案 0 :(得分:3)

通常,您不需要显式设置关系的两面。当您处理多对多关系时,将一个实体一次添加到集合中可能更安全,而不是一次性设置集合。所以,而不是:

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

我会循环遍历featureSections集,并将每个对象逐个添加到section实体的Feature关系中,例如:

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

我希望这会有所帮助......

否则,Apple文档中的this section可能会引起您的兴趣。