2013-11-14 2 views
6

В прошлом я выпустил свое приложение с предустановленной базой данных, поэтому пользователю не нужно было его обновлять при первом запуске. Был какой-то код, который я нашел в другом вопросе на SO (к сожалению, не имеют связей в малейших), что я добавил к моему persistentStoreCoordinator методу App делегата:Предварительная загрузка базы данных в iOS 7

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"db.sqlite"]; 
    if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) 
    { 
     NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"db" ofType:@"sqlite"]]; 
     NSError* err = nil; 

     if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err]) 
     { 
      NSLog (@"Error - Could not preload database."); 
     } 
    } 

//... more code generated from the template here 
} 

Когда я пытаюсь сделать это в прошивке 7, я не получайте никаких ошибок, но база данных пуста (хотя база данных в моем mainBundle имеет всю информацию, которую я ожидаю). Я заметил, что в файле applicationDocumentsDirectory есть больше файлов базы данных (файл .sqlite-shm и файл .sqlite-wal). Нужно ли мне что-то делать с этими файлами? Или уже невозможно иметь предварительно загруженный корабль базы данных с приложением?

EDIT: Я попытался добавить код, чтобы скопировать новые файлы .sqlite-shm и .sqlite-wal, но это не помогает.

ответ

5

Основные данные немного изменились в iOS 7, главным образом, как выполняется сохранение.

Write Ahead Logging (wal) был введен для повышения производительности, а следовательно, для файла sqlite WAL, который вы видите.

Вы можете сказать, ваше приложение, чтобы использовать старый «режим журнала»:

Вы можете задать режим журнала, добавив NSSQLitePragmasOption к опциям при вызове addPersistentStoreWithType: конфигурации: URL: опции: ошибка , Например. чтобы установить предыдущий режим по умолчанию DELETE:

NSDictionary *options = @{ NSSQLitePragmasOption : @{@"journal_mode" : @"DELETE"} }; 

Source

Я не уверен, если это будет исправить вашу проблему, но это большая вещь, которая изменилась с Core Data в прошивке 7

Если вы хотите узнать больше о WAL, я предлагаю смотреть WWDC session #207, "Whats New In Core Data & iCloud"

+0

Да, добавив, что 'options' словарь делает трюк. Я посмотрю видео, которое вы связали, и, надеюсь, это не то, что мне в итоге нужно =). В противном случае, я думаю, мне придется найти другое решение, но сейчас это работает. – GeneralMike

+0

WAL повышает производительность в многопоточных приложениях, поэтому будьте внимательны при изменении режима журнала. Однако я не знаю точно, как отправить предварительно заполненную базу данных с поддержкой WAL. –

+0

@DavidCaunt: Я не слишком беспокоюсь о производительности для своего приложения на данный момент. Операции с базой данных были довольно медленными в предыдущей версии моего приложения, но я значительно урезал множество моих таблиц, чтобы устранить потраченное впустую пространство и изменил мои выборки, чтобы лучше получить информацию, которая мне понадобится в сеансе. После этих изменений практически невозможно обнаружить задержку. Если что-то изменится, и производительность снова начнет страдать, я буду помнить, что еще раз посмотрю на WAL, - спасибо. – GeneralMike

5

Я скопировал .sqlite-ше и .sqlite-вали-файлы, а также и его вес orked:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite"]; 

// Check if the sqlite store exists 
if (![[NSFileManager defaultManager] fileExistsAtPath:storePath]) { 
    NSLog(@"File not found... copy from bundle"); 

    // copy the sqlite files to the store location. 
    NSString *bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite"]; 
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil]; 

    bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite-wal"]; 
    storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite-wal"]; 
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil]; 

    bundleStore = [[NSBundle mainBundle] pathForResource:@"emm_samples" ofType:@"sqlite-shm"]; 
    storePath = [documentsDirectory stringByAppendingPathComponent: @"emm_samples.sqlite-shm"]; 
    [[NSFileManager defaultManager] copyItemAtPath:bundleStore toPath:storePath error:nil]; 
} 
else { 
    NSLog(@"File exists"); 
} 

(на основе: Core Data Store included in App Bundle)

Смежные вопросы