11

私はCoreDataとそれを使用するこのアプリにかなり慣れていません。そして、私は現在、アプリからログアウトしたときにコアデータ全体をクリアする機能に取り組んでいます。

私は2つのsqlliteファイルを持っています(何らかの理由で彼らはそれが便利だと思っていました)

両方のファイルからすべてのデータをクリアして、データのない状態にリセットするにはどうすればよいですか?

私は、ガイドに従って、SOで多くの方法を試しました。

1対多の関係ですべてのCoreDataをクリア/リセットする方法

CoreDataからすべてのオブジェクトを削除する方法

それらはすべて私にとって失敗しているようです。今、私は何を間違えているのだろうかと思っています。そして、おそらく誰かが私の2つのCoreDataファイルを適切な方法でリセットする方法を説明してくれるでしょう。

編集:

//should clear the whole coredata database. mainly used for logout mechanism
-(void)resetCoreData
{
    for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores)
    {
//    NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
        NSError *error;
        NSURL *storeURL = store.URL;
        DLog(@"storeURL: %@", storeURL);
        NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
        [storeCoordinator removePersistentStore:store error:&error];
        [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

        DLog(@"There are erreurs: %@", error);
//    [self addDefaultData];
    }

    _persistentStoreCoordinator = nil;
    _managedObjectContext = nil;
    _managedObjectModel = nil;
}

これは私にとってCoreDataをクリアしていないようです。

EDIT2:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil) {
        return __managedObjectModel;
    }

    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyName" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return __managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (__persistentStoreCoordinator != nil) {
        return __persistentStoreCoordinator;
    }

    NSString *storePath = [[self applicationDocumentsDirectory]

                           stringByAppendingPathComponent:@"MyName.sqlite"];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    // If the expected store doesn't exist, copy the default store.
    if (![fileManager fileExistsAtPath:storePath]) {
        NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"MyName" ofType:@"momd"];
        if (defaultStorePath) {

            [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];

        }

    }



    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];

    //Check to see what version of the current model we're in. If it's >= 2.0,
    //then and ONLY then check if migration has been performed...
    NSSet *versionIdentifiers = [[self managedObjectModel] versionIdentifiers];
    DLog(@"Which Current Version is our .xcdatamodeld file set to? %@", versionIdentifiers);

    if ([versionIdentifiers containsObject:@"2.0"])
    {
        BOOL hasMigrated = YES;
        if (hasMigrated==YES) {
            storePath = nil;
            storePath = [[self applicationDocumentsDirectory]
                         stringByAppendingPathComponent:@"MyName2.sqlite"];

        }
    }

    NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
    NSError *error;
    NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                                [NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
                                nil];

    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                    configuration:nil
                                                              URL:storeUrl
                                                          options:pscOptions
                                                            error:&error]) {
        DLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return __persistentStoreCoordinator;
}

編集3:アプリ全体を削除して再起動したかのように、CoreDataをリセットする方法をまだ探しています。私の場合、そうする通常の方法はうまくいきません。そして、2つのsqlliteファイルがあります。アプリケーションのある時点で移行が行われたというヒントがありますが、いつ、どのように行うのかよくわかりません。エラーログには何も役に立ちません。

私は最も効率的な方法を探していません。ちょうどその方法。

私を助けてください、そしてその恩恵はあなたのものです。

編集4:最終結果:私のレガシーコードには2番目のManagedObjectContextがインスタンス化されているようでした。それを取り出してフラッシュ機能を実行した瞬間。必要に応じて、両方のsqliteファイルが消えました。

私の問題に力を入れてくれたすべての人に感謝します。

4

4 に答える 4

38

次の方法を試してデータベースをフラッシュしてください。これは私にとって完璧に機能します。

-(void) flushDatabase{
    [__managedObjectContext lock];
    NSArray *stores = [__persistentStoreCoordinator persistentStores];
    for(NSPersistentStore *store in stores) {
       [__persistentStoreCoordinator removePersistentStore:store error:nil];
       [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
    }
    [__managedObjectContext unlock];
    __managedObjectModel    = nil;
    __managedObjectContext  = nil;
    __persistentStoreCoordinator = nil;
}
于 2013-02-15T00:16:02.410 に答える
2
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

したがって、永続ストアコーディネーターから永続ストアを削除してから、ファイルを削除しようとしています。ただし、コーディネーターからストアを削除するだけでは、ストアに関連付けられているファイルが閉じられていることを保証するのに十分ではありません。閉じられていない場合、ファイルシステムによってファイルの削除が妨げられる可能性があります。ここでARCを使用しているかどうかは質問からわかりませんが、古いコードであると言っているので、使用していない可能性があります。いずれにせよ、ストアを削除すると、ストアが解放されるのではなく自動解放される場合、またはストアへの他の参照をどこかに保持している場合、コーディネーターから削除したからといってストアの割り当てが解除されない場合、ファイルは開いたままになる可能性があります、およびファイルの削除は失敗します。

によって提供されるエラーオブジェクトを確認するだけでなく、実際に何が起こっているかを確認する良い方法は-removeItemAtPath:error:、ファイルシステムを調べて、ファイルを削除しようとした後もファイルがまだ存在するかどうかを確認することです。[オーガナイザー]ウィンドウに移動し、デバイスとアプリケーションを選択して、アプリのサンドボックスのコピーをダウンロードします。これで、ファイルが本当に削除されているかどうかを確認できるはずです。

必要に応じてファイルが削除されていることがわかった場合は、データを復元できる他の方法を探してください。UserAがログアウトし、実行中にUserBがアプリにログインした場合、新しい管理対象オブジェクトコンテキストで開始したことを確認しますか?UserAのデータがMOCに残っている可能性はありますか?その後、新しいストアを作成して追加するときに書き出すことができます。私に起こるもう一つの可能​​性は、iCloudがここで「助けている」ということです。データファイルはDocumentsディレクトリに保存されているようですが、iOSは通常、そのディレクトリにあるファイルをiCloudにバックアップして保存しようとします。おそらく、UserBのデータ用に新しいストアを作成すると、iCloudはUserAのレコードをそのストアに追加し直します。(ありそうもない-iCloudはそれよりも洗練されていると私は確信している-しかしチェックすべきことがある。)

于 2013-02-15T01:58:44.447 に答える
1

私は自分のアプリの1つのAppDelegateでこの関数を使用しています...

- (void)deleteAllCoreData
{
    NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
    NSError *error;
    NSURL *storeURL = store.URL;
    NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
    [storeCoordinator removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

    __persistentStoreCoordinator = nil;
    __managedObjectContext = nil;
    __managedObjectModel = nil;

    [self addDefaultData];
}

CoreDataが使用する永続ストアを削除して残し、コアデータに再度アクセスしたときに新しいストアがセットアップされるようにします。

これは、提供した2番目のリンクで説明されている方法です。

于 2013-02-06T11:13:44.133 に答える
1

アプリがファイルを作成できる場合は、アプリが終了したときにファイルを削除するだけです。貴重なスキーマ情報を持つデータベースの概念があり、ファイルを切り捨てるだけでよい場合、コアデータには当てはまりません...スキーマはコンパイルされたエンティティモデルとxcwhateverファイルにあります。

また、コアデータを永続的にしたくない場合は、間違ったツールを使用しているため、間違って読んだに違いありません。

于 2013-02-07T07:03:31.530 に答える