1

==== 私の解決策==== データベースをメインバンドルに保存し、アプリを更新するたびにデータベースの名前を変更することでこれを解決しました。

モデルの更新などを検討しましたが、思ったように機能しませんでした。

この問題をどのように解決したか

====元の質問====

以前にさまざまな形式でこの質問をしたことをお詫びしますが、おそらく質問の仕方が原因で、解決できませんでした。古い質問は削除しました。

Core Data sqlite 読み取り専用データベースを使用するアプリがあり、データベースの新しいバージョン (レコードに組み込まれたバージョン番号) でアプリを更新しようとしています。手動でターゲットをクリーンアップしてシミュレーターをリセットする以外は、何をしても、古いデータベースが読み取られます。コードを介してこれを行うことができる必要があります。

初期設計中に、同じ問題を解決するために次のように投稿しました: The initial design . 現在、データベースは非常に大きく、最初の起動時に構築するのに多くの時間がかかります。

プロセス:

A.) 新しいデータベース バージョンを XCODE プロジェクトに追加し、Xcode を介して手動でバンドルに追加します

B.) 使用されているデータベースのバージョンを確認します

C.) 新しいデータベースがある場合は、ドキュメント ディレクトリにある古いデータベースを削除し、新しいバージョンをメイン バンドルからドキュメント ディレクトリにコピーします。

D.) 添付のコードでは、キャッシュ ディレクトリも削除して再作成します。キャッシュが原因である可能性があることを指摘する投稿が多数見つかりました。これはテスト用ですが、コードにはまだ含まれています

それにもかかわらず、アプリは更新された sqlite データベースにまだアクセスしていません。

メインバンドルにロードされた新しいデータベースバージョンがあり、バージョンパラメーター「EEEEEE」があります。現在のデータベースを読み取ると、「SSSSSS」パラメーターがあるため、データベースを更新する必要があります。

私はこの問題に取り組んでいて、長い間ウェブを検索していましたが、何が問題なのか理解できません。ドキュメント ディレクトリ内の新しいデータベースにアクセスしないのはなぜですか。

私が得ることができるすべての助けに感謝します。何が起こっているのかを理解しようとするために使用する NSLog を含めたので、コードが奇妙に見えないことを願っています。

トレース (NSLog):

applicationDidFinishLaunchingWithOptions

readQuestion

persistentStoreCoordinator

==>PARAMETER is EEEEEE (000000)

==> Update needed


=======================
====BEFORE REPLACE====
===>CURRENT: SSSSSS: 999999
=======================
replaceDatabase function
=======================

=======================
     DELETE CACHE
=======================

Remove successful

=======================
   CREATE NEW CACHE
=======================

===============================
REMOVE sqlite FROM DOCUMENT DIR
===============================

removeItemAtPath:dbDocumentsPath: /Users/xxxxxx/Library/Application Support/iPhone Simulator/5.1/Applications/912962FC-933E-4305-971B-FF094BBD9051/Documents/database.sqlite

=====================================
CHECK IF sqlite EXIST IN DOCUMENT DIR
=====================================

===FILE DOES NOT EXIST===

========================================
MOVE sqlite FROM BUNDLE TO DOCUMENTS DIR
========================================

==>copyItemAtPath:dbBundlePath<<
====================================
CHECK IF sqlite EXIST IN DOCUMENT DIR
=====================================

===FILE EXIST===

readQuestion

=======================
=====AFTER REPLACE=====
=======================
Updated database is SSSSSS

========>STOP<========= 

delegate.m のコード「didFinishLaunchingWithOptions」は次のとおりです。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
NSLog(@"applicationDidFinishLaunchingWithOptions");
NSLog(@" ");

[window addSubview:navigationController.view];
[window makeKeyAndVisible];

//==CHECK IF DATABASE NEEDS TO BE UPDATED==//
//====Check if database needs to be refreshed====//


AccessQuestionsDB *refreshDB_function = [AccessQuestionsDB new];
qArray = [refreshDB_function readQuestion: 999999];
NSLog(@" ");

//Tell what language DB 
if ([k_DBVERSION isEqualToString:@"999999"]) {
    NSLog(@"==>PARAMETER is SSSSSS (999999)");
} else {
    NSLog(@"==>PARAMETER is EEEEEE (000000)");
}
NSLog(@" ");

//==== CHECK IF DATABASE NEEDS TO BE UPDATED ====//
if ([[qArray objectAtIndex:2] isEqualToString: k_DBVERSION]) {
    // No update needed
    NSLog(@"==> No update needed");
    NSLog(@" ");
}
else {
    NSLog(@"==> Update needed");
    NSLog(@" ");
    NSLog(@" ");
    NSLog(@"=======================");
    NSLog(@"====BEFORE REPLACE====");
    if ([[qArray objectAtIndex:2] isEqualToString:@"000000"]) {
        NSLog(@"===>CURRENT: EEEEEE: %@", [qArray objectAtIndex:2]);
    } else {
        NSLog(@"===>CURRENT: SSSSSS: %@", [qArray objectAtIndex:2]);
    }

    [self replaceDatabase];
}

qArray = [refreshDB_function readQuestion: 999999];
NSLog(@" ");
NSLog(@" ");
NSLog(@"=======================");
NSLog(@"=====AFTER REPLACE=====");
NSLog(@"=======================");
if ([[qArray objectAtIndex:2] isEqualToString:@"000000"]) {
    NSLog(@"Updated database is EEEEEE");
} else {
    NSLog(@"Updated database is SSSSSS");
}

NSLog(@" "); 
NSLog(@"========>STOP<=========");
NSLog(@" ");

exit(0); //>>>>STOP HERE DURING TESTING

return YES;
}

データベースの置換:

- (void)replaceDatabase {
NSLog(@"=======================");
NSLog(@"replaceDatabase function");
NSLog(@"=======================");
NSLog(@" ");

NSFileManager *fileManager = [NSFileManager defaultManager];

// remove old sqlite database from documents directory
NSURL *dbDocumentsURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"database.sqlite"];
NSString *dbDocumentsPath = [dbDocumentsURL path];

//====Cache directory testing====//
//====This is just for testing====//

//===============================//
NSLog(@"=======================");
NSLog(@"    DELETE CACHE");
NSLog(@"=======================");
NSLog(@" ");
if ([fileManager removeItemAtPath: [NSHomeDirectory() stringByAppendingString:@"/Library/Caches"] error: NULL]  == YES)
    NSLog (@"Remove successful");
 else 
    NSLog (@"Remove failed");

NSLog(@"=======================");
NSLog(@"    CREATE NEW CACHE");
NSLog(@"=======================");
NSLog(@" ");    

[fileManager createDirectoryAtPath: [NSHomeDirectory() stringByAppendingString:@"/Library/Caches"] withIntermediateDirectories:NO attributes:nil error:nil];

//===============================//
NSLog(@"===============================");
NSLog(@"REMOVE sqlite FROM DOCUMENT DIR");
NSLog(@"===============================");
NSLog(@" ");


if ([fileManager fileExistsAtPath:dbDocumentsPath]) {
    NSError *error = nil;
    [fileManager removeItemAtPath:dbDocumentsPath error:&error];
    NSLog(@"removeItemAtPath:dbDocumentsPath: %@",dbDocumentsPath);
    NSLog(@" ");
    
    if (error) {
        NSLog(@"Error deleting sqlite database: %@", [error localizedDescription]);
    }
} else {
    NSLog(@"file does not ExistsAtPath:dbDocumentsPath: %@",dbDocumentsPath);
    NSLog(@" ");
}


NSLog(@"=====================================");
NSLog(@"CHECK IF sqlite EXIST IN DOCUMENT DIR");
NSLog(@"=====================================");
NSLog(@" ");
if ([fileManager fileExistsAtPath:dbDocumentsPath]) {
    NSLog(@"===FILE EXIST===");
} else {
    NSLog(@"===FILE DOES NOT EXIST===");
}
 NSLog(@" ");    
    

// move new sqlite database from bundle to documents directory
NSLog(@"========================================");
NSLog(@"MOVE sqlite FROM BUNDLE TO DOCUMENTS DIR");
NSLog(@"========================================");
NSLog(@" ");
NSString *dbBundlePath = [[NSBundle mainBundle] pathForResource:@"database" ofType:@"sqlite"];
if (dbBundlePath) {
    NSError *error = nil;
    [fileManager copyItemAtPath:dbBundlePath toPath:dbDocumentsPath error:&error];
    NSLog(@"==>copyItemAtPath:dbBundlePath<<");
    if (error) {
        NSLog(@"Error copying sqlite database: %@", [error localizedDescription]);
    }
}

NSLog(@"=====================================");
NSLog(@"CHECK IF sqlite EXIST IN DOCUMENT DIR");
NSLog(@"=====================================");
NSLog(@" ");
if ([fileManager fileExistsAtPath:dbDocumentsPath]) {
    NSLog(@"===FILE EXIST===");
} else {
    NSLog(@"===FILE DOES NOT EXIST===");
}
NSLog(@" ");
}

persistStoreCoordinator:

// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
NSLog(@"persistentStoreCoordinator");

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

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"database.sqlite"];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}  



    return persistentStoreCoordinator;
}

読む質問:

- (NSMutableArray *)readQuestion: (int)questionNr {

NSLog(@"readQuestion");

NSMutableArray *read_Question = [[NSMutableArray alloc] initWithCapacity: 0];

NSError *error;
//=========PREPARE CORE DATA DB===========//
if (managedObjectContext == nil) { managedObjectContext = [(xxxxxAppDelegate *)
                                                           [[UIApplication sharedApplication] delegate] managedObjectContext]; }
// Define qContext
NSManagedObjectContext *qContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"questions" inManagedObjectContext:qContext];
[fetchRequest setEntity:entity];

NSString *qNR = [NSString stringWithFormat:@"%d", questionNr];

if (questionNr == 999999) { // This is the call to check if database should be updated
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"(question = %@)", @"Hur mycket är 37532 * 3?"];
    [fetchRequest setPredicate: pred];
}
else {
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"(idQ = %@)", qNR];
    [fetchRequest setPredicate: pred];
}


NSManagedObject *matches = nil;

NSArray *objects = [qContext executeFetchRequest:fetchRequest error:&error];

if ([objects count] == 0) {     // If no match refresh database
    [read_Question addObject:@"Update_DB"];
    [read_Question addObject:@"Update_DB"];
    [read_Question addObject:@"Update_DB"];
    [read_Question addObject:@"Update_DB"];
} else {
    matches = [objects objectAtIndex:0];
    [read_Question addObject:[matches valueForKey:@"question"]];
    [read_Question addObject:[matches valueForKey:@"qRightAnswer"]];
    [read_Question addObject:[matches valueForKey:@"qWrongAnswer1"]];
    [read_Question addObject:[matches valueForKey:@"qWrongAnswer2"]];
}

[fetchRequest release];

return [read_Question autorelease];
}
4

1 に答える 1

0

うーん、興味深い質問です。理論はあるけど。まず第一に、私があなたのコードを正しく読んでいれば、データベースのバージョンを把握するために Persistent Store Coordinator を取得しています。これは、古い sqlite ファイルを参照する Persistent Store Coordinator を作成しています。これはよくわからない部分です。古いファイルへのハンドルを持っているので、それを削除しても、Persistent Store Coordinator はまだ古いファイルを参照していると思われます。試してみたいことの 1 つは、sqlite ファイルを削除して置き換えた後、Persistent Store Coordinator と Managed object Context を nil-out することです。また、永続ストア コーディネーターと管理対象オブジェクト コンテキストを初期化する前に、単純に sqlite が古くなっていると想定し、それを置き換えてみます。

于 2012-07-16T21:27:04.050 に答える