1

UITableViewiOS 5に、XMLからデータをダウンロードし、テーブルビューコントローラーを使用してそれらを表示するカタログアプリケーションがありますNSFetchedResultsController。データはCoreDataに保存されますUIManagedDocument。データのダウンロードとインポート時にメインキューをブロックしたくないため、データをダウンロードするためのバックグラウンドキューと、親としてデータをインポートするための新しい子NSManagedObjectContextを作成しました。データのインポートが完了すると、子コンテキストで変更が行われ、変更が親コンテキストに伝播されます。カタログを閲覧するとき、必要に応じて追加のデータをインポートします。が自動保存されるまで、すべてが正常に機能しています。NSPrivateQueueConcurrencyTypedocument.managedObjectContext-save:UIManagedDocument

-com.apple.CoreData.SQLDebug 1ドキュメントが自動保存されるタイミングを確認するために、コアデータのSQLデバッグをオンにしました。

重複するIDを持つドキュメントの自動保存オブジェクトが作成された後document.managedObjectContext(すべてのエンティティIDデータベースには一意のIDパラメーターがあります)。

私は何が間違っているのですか?


問題を再現するための簡単なサンプルコードを作成しました。
コードは次のとおりです。http: //dl.dropbox.com/u/20987346/ViewController.m
完全なXcodeプロジェクトは次のとおりです。http://dl.dropbox.com/u/20987346/CoreDataTest.zip

以下は、バックグラウンドでインポートを実行しているメソッドです。

- (void)backgroundImport
{
    static int counter;

    NSManagedObjectContext *backgroundContext;
    backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    backgroundContext.parentContext = self.document.managedObjectContext;

    [backgroundContext performBlock:^{
        NSManagedObject *entity;

        for (int i = 0; i < 2; i++) {
            entity = [self entityWithID:[NSNumber numberWithInt:arc4random() % 20 + 1]
                 inManagedObjectContext:backgroundContext];
            [entity setValue:[NSString stringWithFormat:@"A Name %d", ++counter] forKey:@"name"];
        }

        [self dumpEntitiesInManagedObjectContext:backgroundContext];

        NSError *error;
        [backgroundContext save:&error];
        if (error) NSLog(@"%@ (%@)", [error localizedDescription], [error localizedFailureReason]);

        [backgroundContext.parentContext performBlock:^{
            [self dumpEntitiesInManagedObjectContext:backgroundContext.parentContext];
        }];
    }];
}

このメソッドは2つのエンティティをインポートします。-entityWithID:指定されたID属性を持つエンティティをフェッチし、存在しない場合は、を使用してエンティティを作成しますNSEntityDescription -insertNewObjectForEntityForName:。ログに記録するすべての-dumpEntitiesInManagedObjectContext:エンティティをダンプします(インポートコンテキストで1回、ドキュメントのコンテキストで1回)。

問題は、ドキュメントが自動保存され、追加のインポートが行われると、ログに次のように表示されることです。

[1140b] Entities: 10             [fb03] Entities: 11
[1140b]   2: A Name 1            [fb03]   2: A Name 1
[1140b]   3: A Name 4            [fb03]   3: A Name 4
[1140b]   4: A Name 8            [fb03]   4: A Name 8
[1140b]   5: A Name 12           [fb03]   5: A Name 12
[1140b]   6: A Name 10           [fb03]   6: A Name 10
[1140b]   8: A Name 6            [fb03]   8: A Name 6
[1140b] **12: A Name 11**        [fb03] **12: A Name 11**
[1140b]   13: A Name 9           [fb03] **12: A Name 5**
[1140b]   17: A Name 3           [fb03]   13: A Name 9
[1140b]   18: A Name 2           [fb03]   17: A Name 3
                                 [fb03]   18: A Name 2

インポートコンテキストには10​​個のエンティティがありますが、メインコンテキストには11個のエンティティがあり、ID12のエンティティは重複しています。古いオブジェクトは親コンテキストで変更されていないようですが、代わりに追加されています。

4

2 に答える 2

3

私はまだこの種のことすべてに夢中になっています(Core DataとUIManagedDocumentが連携しています)が、この質問はあなたの状況に対処するかもしれないと思います:CoreData管理対象オブジェクトはSimulatorを再起動するまで関連オブジェクトを表示しません

これには、以下を使用して「通常の」フローの前に一時IDを永続的にすることが含まれます。 [context obtainPermanentIDsForObjects:[inserts allObjects] error:&error]

于 2012-04-19T13:23:30.183 に答える
1

NSEntityDescription私はこの問題に遭遇し、問題を解決するために小さなカテゴリを作成しました。

@implementation NSEntityDescription (PermanentID)
+ (id)insertNewPermanentObjectForEntityForName:(NSString *)entityName
                        inManagedObjectContext:(NSManagedObjectContext *)context
{
    id object = [self insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
    NSError *error;
    if (![context obtainPermanentIDsForObjects:[NSArray arrayWithObject:object] error:&error]) {
        NSLog(@"Permanent ID not given");
    }
    if (error) {
        NSLog(@"%@", error);
    }
    return object;
}

これについては私のサイトで詳しく説明していますが、ここでカテゴリを再現したので、クリックする必要はありません。

于 2012-09-25T20:04:59.393 に答える