核心数据实体关系在启动之间不会保存
我正在编写一个应用程序,它有四个主要实体,它们都通过关系链接。有些是一对一,有些是一对多。初始加载时,三个实体从本地存储的 XML 文件加载数据到应用程序,其中一个实体从 Web 下载 XML 并从中加载数据。当应用程序加载时,它会执行检查以查看每个文件中的数据是否比当前拥有的数据更新,如果是,它将用相应文件中的数据替换该实体中的所有当前数据。
作为写作过程中调试过程的一部分,我一直在强制删除所有数据。当调用删除函数并在应用程序启动时加载所有数据时,应用程序运行良好,并且所有实体和关系都按照应有的方式运行。但是,当我删除对删除函数的调用并执行检查并尝试从其存储的数据运行时,所有关系似乎都消失了。在调试过程中,我发现所有实体确实包含它们应该包含的所有常规数据,只是它们不再具有关系。我不明白为什么在第一次加载时会保存关系,但在不重新导入所有数据时不会保留关系。
我想一些代码会对任何调试都有帮助,但是,我不确定应该包含多少。因此,我将首先仅包含数据加载类中调用的方法之一。如果还有什么有帮助,请告诉我。非常感谢任何帮助。
更新代码:2011 年 2 月 25 日(基于建议 - 问题仍然存在) 更新代码:2011 年 2 月 25 日 - 问题已解决
- (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)这是在删除所有数据并且关系完好后加载应用程序时得到的结果
2)这是当应用程序再次运行而没有先删除和重新加载数据时我得到的结果。底部的选项卡由其中一个实体创建,并且标题略有不同。发生这种情况是因为与 DisplayType 的关系不存在,并且它不知道要加载什么类型的视图控制器,也不知道要为选项卡使用哪个图标。
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
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通常,您不需要显式设置关系的双方。当您处理一对多关系时,一次向集合中添加一个实体可能比一次设置所有集合更安全。因此,
我将循环遍历
featureSections
集合并将每个对象一一添加到Feature
实体的section
关系中,例如:我希望这有帮助...
否则,这个Apple 文档中的 部分可能令人感兴趣。
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:
I would loop through the
featureSections
Set and add each object one by one to thesection
relationship of theFeature
entity, e.g.:I hope this helps...
Otherwise, this section in the Apple documentation might be of interest.