アプリでコアデータを使用しており、次の更新で iTunes ファイル共有を開始したいのですが、最初にアプリの sqlite データベースを移動する必要があります。以下のコードを試してみましたが、起動時にアプリがクラッシュします。NSPersistentStoreCoordinator で古いストアの URL を新しいストアの URL に置き換えるだけでよいと思いました。ここで、「newDatabasePath」は新しいストアの URL と一致します。
次に、sqliteファイルを次のように置き換えます
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//check app has run before and has a current db
if ([saveData boolForKey:@"hasRunBefore"]) {
NSString *oldDatabasePath = [[dirPaths objectAtIndex:0] stringByAppendingPathComponent:@"AppData.sqlite"];
NSString *newDatabasePath = [privateDocsPath stringByAppendingPathComponent:@"AppData.sqlite"];
NSError *error;
if ([fileMgr fileExistsAtPath:newDatabasePath]) {
[fileMgr removeItemAtPath:newDatabasePath error:&error];
[fileMgr copyItemAtPath:oldDatabasePath toPath:newDatabasePath error:&error];
}
[fileMgr removeItemAtPath:oldDatabasePath error:&error];
BOOL databaseMoved = YES;
[saveData setBool:databaseMoved forKey:@"databaseMoved"];
}
}
ありがとう
ここで同様の質問を読んだ後、これを解決するための新しいアプローチを試みました。私はそのようにcoredataスタックをリセットしようとしました
- (void)resetDatabase {
NSPersistentStore* store = [[__persistentStoreCoordinator persistentStores] lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
// release context and model
__managedObjectModel = nil;
__managedObjectContext = nil;
//[__persistentStoreCoordinator removePersistentStore:store error:nil];
__persistentStoreCoordinator = nil;
NSFileManager* fileMgr = [NSFileManager defaultManager];
[fileMgr removeItemAtPath:storeURL.path error:&error];
if (error) {
NSLog(@"filemanager error %@", error);
}
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//create Private Documents Folder
NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libDir = [libPaths objectAtIndex:0];
NSString *privateDocsPath = [libDir stringByAppendingPathComponent:@"Private Documents"];
if (![fileMgr fileExistsAtPath:privateDocsPath])
[fileMgr createDirectoryAtPath:privateDocsPath withIntermediateDirectories:YES attributes:nil error:nil];
NSString *oldDatabasePath = [[dirPaths objectAtIndex:0] stringByAppendingPathComponent:@"AppData.sqlite"];
NSString *newDatabasePath = [privateDocsPath stringByAppendingPathComponent:@"AppData.sqlite"];
BOOL removedItemAtPath = NO;
BOOL copiedItemToPath = NO;
if ([fileMgr fileExistsAtPath:newDatabasePath]) {
DLog(@"DATABASE EXISTS AT PATH");
removedItemAtPath = [fileMgr removeItemAtPath:newDatabasePath error:&error];
if (removedItemAtPath) {
DLog(@"ITEM REMOVED");
}
else
DLog(@"FAILED TO REMOVE ITEM: %@", error);
copiedItemToPath = [fileMgr copyItemAtPath:oldDatabasePath toPath:newDatabasePath error:&error];
if (copiedItemToPath) {
DLog(@"ITEM COPIED");
}
else
DLog(@"FAILED TO COPY ITEM: %@", error);
}
// recreate the stack
__managedObjectContext = [self managedObjectContext];
}
このアプローチでは、アプリを最初に起動したときにコアデータ スタックからデータを読み込もうとすると例外がスローされますが、その後、すべてが正常にリロードされ、「ライブラリ/プライベート ドキュメント」の新しい場所から sqlite ファイルが使用されます。