2

現在、CoreDataを使用するようにアプリを更新しています。あなたが言うことができるアプリは「データベースビューア」であり、一度に1つのデータベースしか表示できません。各データベースは、独自の個別のフォルダーに保持されます。現在、データは一連のplistファイルとしてダウンロードおよび保存されています。

新しいバージョンでは、これらのplistデータベースをCore Dataストア(データベースごとに1つのストア)に変換する必要があります。個別のストアファイルを作成し、エンティティを作成するメソッドを既に設定しました。問題は、すべてのエンティティが「現在の」または「最後に作成された」ファイルではなく、最初に作成したデータベースに保存されることです。

私が使用している基本的なプロセスは次のとおりです。

//For each database {
//Create the sqlite file and set up NSManagedObjectContext
[MagicalRecord setupCoreDataStackWithStoreNamed:
    [NSURL fileURLWithPath:
    [NSString stringWithFormat:@"%@/%@/%@.sqlite",
    dirPath, directory, directory]]];
NSManagedObjectContext *managedObjectContext = 
    [NSManagedObjectContext MR_contextForCurrentThread];

//Iterate through all the plist files and create the necessary entities.
//Save new entities to file
[managedObjectContext MR_save];
//Clean up all cashes
[MagicalRecord cleanUp];
}

どのようにしてストアを適切に切り替え、基本的に各スイッチ間のすべてを「リセット」しますか。できれば(可能であれば)魔法少女を使用してください。

編集:私は問題の一部を見つけ、不要な動作のほとんどを削除しました。[MagicalRecord cleanUp]結局のところ、バックグラウンドスレッドを確実に呼び出すことはできません。また、私が思っていることをしていません(以下を参照)。コアデータスタックをリセットするために、「保存」するたびにメインスレッドにコールバックすることになりました。これを行うと、最初の3つのデータベースの新しいコンテキストが作成されます。その後、3データベース前のデータベースのコンテキストを複製します。したがって、同じ3つのコンテキストがループで使用されます。

これは私が現在持っているものです。バックグラウンドスレッドを作成してプロセスを開始し、コードを実行してバックグラウンドで単一のデータベースを作成します。

backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
    dispatch_async(backgroundQueue, ^(void) {
        [self createSQLiteDatabase:updateList];
    });

次に、スタックとデータベースを作成します。

- (void)createSQLiteDatabase:(NSArray *)updateList
{
    NSString *directory = [updateList objectAtIndex:0];
    [MagicalRecord setupCoreDataStackWithStoreNamed:
        [NSURL fileURLWithPath:[NSString stringWithFormat:@"%@/%@/%@.sqlite",
        dirPath, directory, directory]]];
    NSManagedObjectContext *managedObjectContext = 
        [NSManagedObjectContext MR_contextForCurrentThread];
    //Check to see if the stack has reset
    NSLog(@"Before:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);

    //Create and add entities to context...

    //Prepare for next loop
    NSLog(@"After:%i", [[Competition MR_findAllInContext:managedObjectContext] count]);
    [managedObjectContext MR_saveNestedContexts];
    [NSManagedObjectContext MR_resetContextForCurrentThread];

    NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:updateList];
    [temp removeObjectAtIndex:0];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        [self shouldContinueUpdating:temp];
    });

次に、すべてをリセットして、すべてのデータベースに対して繰り返します。

- (void)shouldContinueUpdating:(NSArray *)databases
{
    //preform cleanup on main thread and release background thread
    [MagicalRecord cleanUp];
    dispatch_release(backgroundQueue);

    if ([databases count] != 0) {
        backgroundQueue = dispatch_queue_create("com.BrandonMcQuilkin.myQueue", NULL);
        dispatch_async(backgroundQueue, ^(void) {
            [self createSQLiteDatabase:databases];
        });
    }
}

2つのNSLogを使用すると、コンソールでこれを取得できます(6つのデータベースを使用すると、変換するデータベースの数に関係なく、パターンは同じです)。

//First Loop
Before:0
After:308
//Second Loop
Before:0
After:257
//Third Loop
Before:0
After:37
//Fourth Loop
Before:308 
After:541 
//Fifth Loop
Before:257
After:490
//Sixth Loop
Before:37
After:270
... Keep adding to each of the three contexts.

そして[MagicalRecord cleanUp]、それがしていると言っていることをしていません。これがメソッドが行うことになっていることです。

+ (void) cleanUpStack;
{
[NSManagedObjectContext MR_cleanUp];
[NSManagedObjectModel MR_setDefaultManagedObjectModel:nil];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:nil];
[NSPersistentStore MR_setDefaultPersistentStore:nil];
}

しかし、保存するたびにNSStoreCoordinatorが同じコーディネーターであり、同じメモリ位置にあり、各ストアがぶらぶらしていることがわかりました。何かが正しく機能していません...

4

2 に答える 2

0

私が抱えている問題は、MagicalRecordのバグが原因であることが判明しました。ここにgitの問題を送信しました:https ://github.com/magicalpanda/MagicalRecord/issues/270

于 2012-10-10T21:03:18.733 に答える
0

MagicalRecordはあなたにとってこの仕事に最適なツールではないかもしれません...

まず、setupCoreDataStackWithStoreNamed:メソッドの使用法を修正しましょう。パラメータは、URLやファイルパスではなく、NSStringを取ります。MagicalRecordは適切なパスを選択し、そこにストアを作成します。結果のsqliteファイルは、意図したパスで名前が付けられる可能性があります。

次に、このファイルのCoreDataモデルを動的に作成する必要があります。これはちょっと難しいですが、可能です。これらのplistファイルをトラバースし、エンティティ、属性、および関係を解釈し、対応するNSEntityDescriptions、NSAttributeDescriptions、およびNSRelationshipDesctiptionsを作成して、NSManagedObjectModelに「手動で」入力する必要があります。あなたは方法を探したいでしょう

- [NSManagedObjectModel setEntities:(NSArray *)]

NSEntityDescription、NSAttributeDescription、NSRelationshipDescriptionの作成メソッドも同様です。

また、このモデルをどこかに保存して、毎回再作成する必要がないようにすることもできます。幸い、NSCodingに準拠しているため、ディスクに保存できるはずです。

その後、おそらくデータを入力する必要があります。ここから、MagicalRecordがお手伝いします。Cocoa isMyGirlfriendのために書いたImportingDataMadeEasyのブログ投稿をご覧になることをお勧めします

「ストアを切り替える」場合、つまり、取得したplistファイルごとに新しいストアを作成する場合は、ファイルごとにCoreDataスタック全体を破棄する必要があります。このプロジェクトでMagicalRecordを使用する場合は、[MagicalRecordcleanUp]を確認して最初からやり直す必要があります。各モデルが同じである場合は、永続ストアコーディネーターをリリースし、ストアに新しいモデルを作成することで解決できます。ただし、「スキーマ」はおそらく異なるため、すべてをスクラッチして最初からやり直す必要があります。

于 2012-10-03T02:04:17.130 に答える