0

「アクセスしていない」sqlite DB に関する説明: NSBundle に .sqlite があり、.sqlite のファイル サイズが正しいサイズであるにもかかわらず、コンテキスト/ストアは、デバイス上でのみ .sqlite のエントリを検出できません。シミュレーターでは、コンテキスト/ストアは正常に動作します。

私はこれにかなり困惑しています。モデル バージョンを xcdatamodeld に追加しました。バージョンをリセットし、コードで自動的に移行を行い、データベースを再作成しました。

iPhoneシミュレーターでは動作します。ただし、デバイスをオフにして実行すると、データベースからの読み取りに失敗します。

sqllite が実際にデバイス上にあることを検出し、ファイル サイズも確認するコードを挿入しました。SQLLite は NSBundle から正しくコピーされており、ファイル サイズもデータがあることを示しています。

どういうわけか、私のコードはデバイス上の DB へのアクセスを拒否しています。これはなぜですか?DB にアクセスするためのコードは変更されていません。変更されたのはデータモデルだけです。以下のコードは、アップグレード前のデバイスで機能していました。

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
    return _managedObjectContext;
}

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

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
  if (_managedObjectModel != nil) {
    return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"sirona" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
    return _persistentStoreCoordinator;
}

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"sirona.sqlite"];

NSString *databasePath = [NSBundle.mainBundle pathForResource:@"sirona" ofType:@"sqlite"];
NSLog(@"File manager: %@", [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] bundlePath] error:nil]);
NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath: @"sirona.sqlite" error: NULL];
UInt32 result = [attrs fileSize];
NSLog(@"File size: %d", (unsigned int)result);
NSError *error = nil;

// important part starts here
   NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                            [NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption,
                            [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                                                           nil];

_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}

return _persistentStoreCoordinator;
}

コアデータを介してDBにアクセスする方法:

  NSFetchRequest *request = [[NSFetchRequest alloc] init];
  [request setEntity:[NSEntityDescription entityForName:@"Representative" inManagedObjectContext:context]];
  [request setIncludesSubentities:NO]; //Omit subentities. Default is YES (i.e. include subentities)

  NSError *err;
  NSUInteger count = [context countForFetchRequest:request error:&err];
  NSLog(@"Count: %lu", (unsigned long)count);

編集:デバイスにコピーするコードがないと、これがどのように機能していたのかわかりません。しかし、現在は機能しているようです。

これを行うコード:

NSURL *storeURL = [[self applicationDocumentsDirectory]    URLByAppendingPathComponent:@"sirona.sqlite"];

if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {
    NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"sirona" ofType:@"sqlite"]];
    NSLog(@"PreloadURL: %@", preloadURL);
    NSError* err = nil;

    if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err]) {
        NSLog(@"Oops, could copy preloaded data");
    }
}

NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
4

1 に答える 1

0

CoreData コンテキストを初期化する前に、読み取り/書き込み権限を持つフォルダーに sqlite ファイルをコピーする必要があります。

于 2013-06-26T16:33:10.887 に答える