2012-06-20 29 views
10

Tengo una aplicación que utiliza MagicalRecord, y estoy completando la base de datos con una gran cantidad de datos que se utilizan como referencia. Dentro de ese mismo modelo de datos, tengo información definible por el usuario relacionada con cosas que el usuario puede hacer en la aplicación.MagicalRecord: bases de datos múltiples

La aplicación fue rechazada porque se supone que los datos rellenos previamente están marcados como "no hacer copia de seguridad". Entonces, me gustaría tener esos datos en un almacén de datos por separado para poder mantener los datos del usuario como backupable.

¿Hay alguna manera de tener dos almacenes de datos separados usando MagicalRecord?

Respuesta

15

Creo que es posible, pero no demasiado fácil. Como ya sabe, para trabajar con más de una base de datos, debe llevar algunos cambios a su PersistentStoreCoordinator, por lo que tendrá dos PersistentStores. Después de esto, la pila de datos básicos se vería así: enter image description here

La otra forma es que dos hagan dos proveedores de almacenes PersistentStore por separado, cada uno con una tienda.

En Mágico de grabación, hay varios métodos de clase para añadir tiendas en NSPersistentStoreCoordinator + MagicalRecord.h.

  • (NSPersistentStore *) MR_addInMemoryStore;
  • (NSPersistentStore *) MR_addAutoMigratingSqliteStoreNamed: (NSString *) storeFileName;
  • (NSPersistentStore *) MR_addSqliteStoreNamed: (id) storeFileName withOptions: (__ autoreleasing NSDictionary *) opciones;

creo, que este es el lugar donde se puede hacer lo que quiere.

También debo mencionar, que todo el proccess de la creación de la pila va en MagicalRecord + Setup.h

+ (void) setupCoreDataStackWithStoreNamed:(NSString *)storeName 

Así que usted puede añadir sus tiendas y Coordinadores allí. Nunca lo he logrado, solo fue una breve investigación de una posible solución.

6

Pude resolver este problema utilizando configuraciones. Como Magical Record siempre envía null para el parámetro de configuración, rompí setupCoreDataStackWithAutoMigratingSqliteStoreNamed y lo sustituí por un método que admite múltiples configuraciones.

Como Magical Record hace un buen trabajo al manejar las migraciones automáticas, primero llamo al setupCoreDataStackWithAutoMigratingSqliteStoreNamed, le sigo la limpieza y luego proporciono el código de reemplazo.

Tengo un modelo de objeto con mis objetos de datos semilla asignados a la configuración "Semilla" y objetos de usuario asignados a la configuración de "Usuario". Magical Record ya se ha inicializado para que pueda migrar automáticamente si es necesario.

+(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]; 
} 

Además, MR 3.0 tiene pilas concurrentes que pueden resolver el problema una vez que se ha completado.

+0

Hola @Ron, ¿qué tienda pasas a setupCoreDataStackWithAutoMigratingSqliteStoreNamed ya que tienes dos? ¿El que no tiene semilla? – DAN

0

Mantener los datos para diferentes entidades de Datos centrales en diferentes archivos de tienda es bien soportado y bastante sencillo. Sin embargo, MagicalRecrd no proporciona ningún método de conveniencia para configurar su pila de Datos Core de esta manera. Simplemente tiene que asignar su pila manualmente y decirle a MagicalRecord que use el NSPersistentStoreCoordinator que crea. He aquí cómo lo hice en rápida:

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) ") 
     } 
    } 
} 

Tenga en cuenta que en mi código que estoy haciendo referencia a su concepto de la tienda "semilla" como "contenido" y la tienda definibles por el usuario como "usuario".

Para completar el segundo aspecto de su pregunta, configurar el almacén de contenido para que no se realice una copia de seguridad, simplemente tiene que jugar con las URL donde almacena cada tienda, colocando el almacén de contenido en un directorio temporal sin copia de seguridad y copiarlo en esa ubicación desde su paquete de aplicaciones si no existe.

Cuestiones relacionadas