1

アプリのバックアップ/復元機能を実装していますが、バックアップから sqlite ファイルを復元し、いくつかのデータにアクセスしようとすると、次のエラーが発生します。

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Object's persistent store is not reachable from this NSManagedObjectContext's coordinator'

ARC の前に戻って、appdelegate の Core Data オブジェクトをゼロにすることができ、ManagedObjectContext にアクセスしようとすると再構築されていました。今はどうしていますか?

編集:

私は何か他の間違ったことをしているに違いありません。管理オブジェクト コンテキストを読み取り専用に設定できませんが、データにアクセスしようとすると同じエラーが発生します。何かアドバイス?

- (void)restoreDatabase {

    ICAMAppDelegate *appDelegate = (ICAMAppDelegate *)[[UIApplication sharedApplication] delegate];
    appDelegate.managedObjectContext = nil;
    NSError *error;

    // Delete Persistent Store
    NSArray *stores = [[appDelegate persistentStoreCoordinator] persistentStores];
    NSPersistentStore *store = [stores objectAtIndex:0];
    NSURL *storeURL = store.URL;
    [[appDelegate persistentStoreCoordinator] removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

    NSString * databaseName = @"ICAMMobile.sqlite";
    NSString * databaseBackupName = @"ICAMMobile.sqlite.bak";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    NSString *backupPath = [documentsDir stringByAppendingPathComponent:databaseBackupName];
    NSString *dbPath = [documentsDir stringByAppendingPathComponent:databaseName];

    if([fileManager fileExistsAtPath:backupPath])
    {
        if (![fileManager copyItemAtPath:backupPath toPath:dbPath error:&error])
        {
            NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
        }
        else
        {
            [appDelegate.managedObjectContext reset];
        }
    }
}
4

1 に答える 1

6

これがうまくいきました。[appDelegate persistentStoreCoordinator] addPersistentStoreWithTypeファイルを置き換えた後に電話する必要がありました。

編集: おまけとして、バックアップ データベース メソッドも追加しました。

- (void)restoreDatabase {
    ICAMAppDelegate *appDelegate = (ICAMAppDelegate *)[[UIApplication sharedApplication] delegate];
    NSError *error;
    // Delete Persistent Store
    NSArray *stores = [[appDelegate persistentStoreCoordinator] persistentStores];
    NSPersistentStore *store = [stores objectAtIndex:0];
    NSURL *storeURL = store.URL;
    [[appDelegate persistentStoreCoordinator] removePersistentStore:store error:&error];
    [[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];

    NSString * databaseName = @"ICAMMobile.sqlite";
    NSString * databaseBackupName = @"ICAMMobile.sqlite.bak";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    NSString *backupPath = [documentsDir stringByAppendingPathComponent:databaseBackupName];
    NSString *dbPath = [documentsDir stringByAppendingPathComponent:databaseName];

    if([fileManager fileExistsAtPath:backupPath])
    {
        if (![fileManager copyItemAtPath:backupPath toPath:dbPath error:&error])
        {
            NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
        }
        else
        {
            [[appDelegate persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];
        }
     }
}


- (void)backupDatabase {
    NSString * databaseName = @"ICAMMobile.sqlite";
    NSString * databaseBackupName = @"ICAMMobile.sqlite.bak";
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDir = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    NSString *backupPath = [documentsDir stringByAppendingPathComponent:databaseBackupName];
    NSString *dbPath = [documentsDir stringByAppendingPathComponent:databaseName];

    NSURL *toURL = [NSURL fileURLWithPath:backupPath];

    if([fileManager fileExistsAtPath:backupPath])
    {
        //get rid of the old copy, only one allowed
        [fileManager removeItemAtPath:backupPath error:&error];
    }

    if([fileManager fileExistsAtPath:dbPath])
    {
        if ([fileManager copyItemAtPath:dbPath toPath:backupPath error:&error]) {
            [toURL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:&error];
        } else {
            NSLog(@"Failed to create writable database file with message '%@'.", [error localizedDescription]);
        }
    }
}
于 2013-01-29T23:05:16.243 に答える