我正在阅读一个基本上如下的XML文件:
<teams>
<team id = "A1">
<player>Tom</player>
<player>Dick</player>
<player>Harry</player>
</team>
<team id = "A2">
<player>John</player>
<player>Tom</player>
</team>
</teams>
我使用NSXMLParser并在didEndElement
委托方法中创建核心数据实体,如下所示:
if ([elementName isEqualToString:@"player"]) {
if ([nodeContent length] != 0) {
player = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:savedContext];
player.name = nodeContent;
}
}
为didStartElement
上的'团队'做类似的事情。 “nodeContent
”就是我从foundCharacters
得到的。到现在为止还挺好。一切正常。但是,在这个例子中,我有一个玩家(汤姆),他在两个队中打球。这是可能的,但我不想在我的核心数据中使用Tom的两个实体。所以,我检查一下这个名字的玩家是否已经存在:
Player *player = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Player"];
request.predicate = [NSPredicate predicateWithFormat:@"name = %@", nodeContent];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSError *error = nil;
NSArray *players = [savedContext executeFetchRequest:request error:&error];
if (!players || ([players count] > 1)) {
NSLog(@"WTF?!");
} else if ([players count] == 0) {
player = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:savedContext];
player.name = nodeContent;
} else {
player = [players lastObject];
}
[player addPlaysInTeamObject:team];
......如果是这样的话,我只是使用那个实体。如果没有,我会像以前一样创建一个新的。
现在,当我在前台同步运行解析时,这一切都有效,但我不想在下载内容时冻结我的应用程序。所以我把所有这些放在一个线程中。它有时可以正常工作,但偶尔我会在executeFetchRequest
上收到以下错误:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x8177a90> was mutated while being enumerated.'
*** First throw call stack:
(0x12d3022 0x1784cd6 0x12d2bf1 0x41314 0xd5b9 0xceaa25 0x19118f6 0x191dab0 0xce901d 0xcf8d 0xc3a5 0x1f31330 0x1f32439 0x908b9b24 0x908bb6fe)
terminate called throwing an exception(lldb)
当我不使用(前景)UI时会发生这种情况,但是当我触摸任何UI元素时总是,即使该UI元素不使用我正在加载的数据的背景。我检查了这个论坛并得出结论,它可能是由解析器填满数据库引起的,同时NSFetchRequest
使用数据库来搜索某个名称。 (虽然我真的不明白,因为所有这些都发生在同一个线程中。)
有没有人可以告诉我我做错了什么?
谢谢!
- GB
答案 0 :(得分:0)
显然,当另一个线程仍在创建/更新核心数据数据库时,您无法访问核心数据实体。
在这种情况下,我最终分离了XML解析和核心数据创建。基本上,我解析整个XML内容并将其存储在NSDictionary中。之后,我使用上面的算法来查找或创建具有该NSDictionary的核心数据实体。