0

基本的に次のような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>

didEndElementNSXMLParserを使用し、次のようにデリゲートメソッドでCoreDataエンティティを作成します。

if ([elementName isEqualToString:@"player"]) {
    if ([nodeContent length] != 0) {
        player = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:savedContext];            
        player.name = nodeContent;
    }
}

そして、の「チーム」についても同様のことを行いdidStartElementます。' nodeContent'は私が得たものfoundCharactersです。ここまでは順調ですね。すべて問題なく動作します。ただし、この例では、2つのチームでプレーするプレーヤー(Tom)がいます。これは可能ですが、コアデータにトムの2つのエンティティを含めたくありません。そこで、その名前のプレイヤーがすでに存在するかどうかを確認します。

    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

4

1 に答える 1

0

どうやら、別のスレッドがまだコアデータデータベースを作成/更新している間は、コアデータエンティティにアクセスできません。

この場合、XMLの解析とコアデータの作成を分離することになりました。つまり、基本的には、XML全体を解析して、NSDictionaryに格納します。その後、上記のアルゴリズムを使用して、そのNSDictionaryでコアデータエンティティを検索または作成します。

于 2012-08-09T07:22:34.390 に答える