2012-06-20 8 views
10

У меня есть приложение, которое использует MagicalRecord, и я предварительно заполняю базу данных большим количеством данных, которые используются для справки. В пределах той же модели данных у меня есть определяемая пользователем информация, относящаяся к вещам, которые пользователь может делать в приложении.MagicalRecord: несколько баз данных

Приложение было отклонено, поскольку предварительно заполненные данные должны быть помечены как «не делать резервные копии». Поэтому я хотел бы иметь эти данные в отдельном хранилище данных, чтобы я мог хранить данные пользователя как резервные.

Есть ли способ иметь два отдельных хранилища данных, используя MagicalRecord?

ответ

15

Я думаю, что это возможно, но не слишком легко. Как вы знаете, для работы с несколькими базами данных вы должны внести некоторые изменения в свой PersistentStoreCoordinator, поэтому у него будет два PersistentStores. После этого вы создадите стек Core Data таким образом: enter image description here

Другой способ состоит из двух отдельных постоянныхStoreCoordinators, каждый из которых имеет один магазин.

В Magical записи, существует несколько методов класса для добавления магазинов в NSPersistentStoreCoordinator + MagicalRecord.h.

  • (NSPersistentStore *) MR_addInMemoryStore;
  • (NSPersistentStore *) MR_addAutoMigratingSqliteStoreNamed: (NSString *) storeFileName;
  • (NSPersistentStore *) MR_addSqliteStoreNamed: (id) storeFileName withOptions: (__ autoreleasing NSDictionary *) опции;

Я думаю, что это то место, где вы могли бы делать то, что вы хотите.

Также я должен отметить, что все proccess установки в стек идет в MagicalRecord + Setup.h

+ (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName 

Таким образом, вы можете добавить свои магазины и координатор там. Я никогда не справлялся с этим сам, это было просто краткое исследование возможного решения.

6

Я смог решить эту проблему с помощью конфигураций. Поскольку Magical Record всегда отправляет null для параметра конфигурации, я разложил setupCoreDataStackWithAutoMigratingSqliteStoreNamed и заменил его на метод, который поддерживает несколько конфигураций.

Поскольку Magical Record отлично справляется с обработкой автоматических миграций, я сначала вызываю setupCoreDataStackWithAutoMigratingSqliteStoreNamed, а затем очищает, а затем предоставляю код замены.

У меня есть одна объектная модель с моими объектами семенных данных, которым назначена конфигурация «Семя» и пользовательские объекты, назначенные для конфигурации «Пользователь». Магическая запись уже была инициализирована, поэтому при необходимости можно автоматически выполнить миграцию.

+(void) RB_setupMultipleStores:(NSString *) seedStoreName userStore:(NSString *) userStoreName 
/* change persistent store to one with multiple configurations. Assumes Magical Record is initialized. */ 
{ 
NSError * error= nil; 

[MagicalRecord cleanUp]; 

NSManagedObjectModel * model = [NSManagedObjectModel MR_defaultManagedObjectModel]; 

NSURL *seedURL = [NSPersistentStore MR_urlForStoreName:[seedStoreName stringByAppendingString:@".sqlite"]]; 

NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model]; 

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
         [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, 
         [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, 
         nil]; 

NSPersistentStore * seedStore =[coordinator 
            addPersistentStoreWithType:NSSQLiteStoreType 
            configuration:@"Seed" 
            URL:seedURL 
            options:options 
            error:&error]; 
if (!seedStore || error) 
{ 
    NSLog(@"Error setting up seed store:%@ for %@", [error localizedDescription], seedURL); 
    exit(-1); 
} 

NSURL *userURL = [NSPersistentStore MR_urlForStoreName:[userStoreName stringByAppendingString:@".sqlite"]]; 

NSPersistentStore * userStore = [coordinator 
           addPersistentStoreWithType:NSSQLiteStoreType 
           configuration:@"User" 
           URL:userURL 
           options:options 
           error:&error]; 

if (!userStore || error) 
{ 
    NSLog(@"Error setting up user store:%@ for %@", [error localizedDescription], userURL); 
    exit (-1); 
} 
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator]; 

[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator]; 
} 

Кроме того, MR 3.0 имеет одновременные стеки, которые могут решить проблему после ее завершения.

+0

Привет @Ron, в каком магазине вы переходите к setupCoreDataStackWithAutoMigratingSqliteStoreNamed, поскольку у вас есть два из них? Тот, у которого нет семени? – DAN

0

Сохранение данных для разных объектов Core Data в разных файлах хранилища хорошо поддерживается и довольно просто. Тем не менее, MagicalRecrd не предоставляет никаких удобных методов для настройки вашего пакета Core Data таким образом. Вам просто нужно выделить свой стек вручную и сообщить MagicalRecord, чтобы использовать созданный вами NSPersistentStoreCoordinator. Вот как я это сделал в стриже:

import Foundation 
import CoreData 
import MagicalRecord 

class CoreDataSetup { 
    static func setupAutoMigratingStack(withContentConfigurationName contentConfigurationName: String, userConfirgurationNameName: String) { 
     MagicalRecord.cleanUp() 

     let managedObjectModel = NSManagedObjectModel.MR_defaultManagedObjectModel() 
     let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel!) 

     let contentURL = NSPersistentStore.MR_urlForStoreName(contentConfigurationName + ".sqlite") 
     let userURL = NSPersistentStore.MR_urlForStoreName(userConfirgurationNameName + ".sqlite") 
     let options = [ 
      NSMigratePersistentStoresAutomaticallyOption : true, 
      NSInferMappingModelAutomaticallyOption: true, 
      NSSQLitePragmasOption: ["journal_mode": "DELETE"] 
     ] 
     do { 
      try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: contentConfigurationName, URL: contentURL, options: options) 
      try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: userConfirgurationNameName, URL: userURL, options: options) 

      NSPersistentStoreCoordinator.MR_setDefaultStoreCoordinator(persistentStoreCoordinator) 
      NSManagedObjectContext.MR_initializeDefaultContextWithCoordinator(persistentStoreCoordinator) 
     } catch { 
      print("Error adding persistent store to coordinator: \(error) ") 
     } 
    } 
} 

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

Чтобы выполнить второй аспект вашего вопроса, настроив хранилище содержимого, чтобы он не был скопирован, вам просто нужно поиграть с URL-адресами, в которых вы храните каждый магазин, помещая хранилище содержимого в резервный временный каталог без резервной копии , и копировать его в это место до запуска из вашего пакета приложений, если он не существует.

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