2009-11-19 18 views
6

En un proyecto anterior, construí una aplicación de iPhone para 2.2.x que usaba SQLite. Tenía datos existentes (en formato XML) que debían precargarse en la compilación. Así que escribí una pequeña herramienta que usaba libxml2 para analizar el XML y luego escribía una base de datos SQLite, que luego se incluía directamente en la compilación como recurso. Esto funcionó muy bien.¿Precargar los datos existentes en una aplicación de iPhone basada en Core Data?

Voy a comenzar un nuevo proyecto para un cliente diferente en unas pocas semanas que tiene casi todos los mismos parámetros. Tendré algunos datos existentes que necesitaré analizar y volcar en un archivo que mostrará la aplicación. Sin embargo, esta vez me gustaría usar Core Data y construir la aplicación para dispositivos 3.x. Sin embargo, no tengo acceso explícito y directo al esquema de base de datos subyacente que utiliza Core Data. (¿Cuál es el tipo de punto de Core Data?)

¿Cómo puedo cargar previamente los datos existentes en una aplicación de iPhone basada en Core Data? ¿Puedo automatizar el proceso (similar a lo que hice arriba con SQLite)?

Respuesta

3

Suponiendo que está utilizando CoreData con un respaldo SQLite, entonces absolutamente. La opción más directa sería dejar que la aplicación genere el esquema por usted, luego usar ese DB vacío/shell, ejecutar su herramienta de migración xml a sql. Solo necesita actualizar su herramienta para tener en cuenta la estructura que CoreData genera para usted desde xcdm.

Alternativamente, podría usar su herramienta para escribir un sqlite db incluido en su paquete, luego en tiempo de ejecución al inicio, leer los datos de sqlite db, escupirlo en CoreData y continuar. Esto usaría su base de datos sqlite como el contenedor para los "datos de precarga", y toda la interacción de datos adicional dentro del almacén de datos de CoreData.

Probablemente es una cuestión de preferencia.

+1

Por aplicación, ¿quiere decir que deje que Xcode genere el esquema? ¿O el esquema solo se genera en tiempo de ejecución? –

+0

No estoy 100% seguro. Quiero decir que se genera en tiempo de ejecución (creo que parte de la iniciación de CoreData es actualizar un almacén de datos si es necesario), pero necesitaría verificarlo dos veces. –

+0

Xcode no generará el esquema. Es una operación en tiempo de ejecución. –

2

No creo que Core Data proporcione este tipo de funcionalidad inherentemente. Si estuviera en su lugar, escribiría una pequeña herramienta que realizara el análisis XML e hiciera lo que fuera necesario para crear el modelo Core Data a partir de esos datos y persistir. Luego, simplemente mueva la base de datos sqlite que Core Data genera a su proyecto real.

Luego, quizás escriba algún código que copie esa base de datos predeterminada en la ubicación correcta en el iPhone si aún no existe una base de datos allí. Eso también le permitirá volver fácilmente a los datos "limpios" si se encuentra mal, ya que puede eliminar el archivo de la base de datos y volver a ejecutar la aplicación.

+0

He hecho algo como lo que describiste, pero en lugar de hacerlo en dos pasos, lo hago en uno. Creo la tienda .sql donde se necesita en el iPhone. Sin embargo, ¿este enfoque no causaría problemas cuando llegue el momento de enviar la aplicación a la tienda de aplicaciones? ¿Cómo corregirías este problema? – Stunner

+0

¿Por qué esto causaría problemas? No creo que incluir los datos iniciales con su aplicación vaya en contra de las pautas de la App Store. –

2

Puede seguir un enfoque similar. La forma más fácil es configurar el contexto administrado de datos centrales y luego leer en su archivo XML, creando los objetos administrados a medida que analiza el archivo XML.

NSManagedObjet *managedObject = [[NSEntityDescription insertNewObjectForEntityForName:@"DataTypeName" 
                    inManagedObjectContext:managedContext] retain]; 

    [managedObject setValue:@"some data" forKey:@"keyName"]; 
    /* ... */ 
+0

Esta es una solución válida. Sin embargo, preferiría hacer este tipo de análisis "fuera de línea", por lo que la aplicación solo ve un archivo SQLite DB. –

10

Llego un poco tarde a esta fiesta, pero estoy haciendo algo similar para GroceryList. Tengo datos almacenados en archivos plist que necesito en mi tienda CoreData sqlite. Escribí una herramienta de línea de línea de comandos que se ejecuta en mi Mac, que analiza los archivos plist y luego utiliza mi modelo de objetos Core Data para crear una tienda sqlite. Ejecuto esta herramienta de línea de comandos como parte de mi compilación (para algunas configuraciones de compilación) para que pueda regenerar los datos a voluntad. Para crear este tipo de herramienta en xcode, seleccione Archivo -> Nuevo proyecto -> Mac OS X -> Herramienta de línea de comandos y seleccione "Datos principales" en el menú "Tipo". Aquí hay un código de muestra:

#import <objc/objc-auto.h> 

int main (int argc, const char * argv[]) { 

    objc_startCollectorThread(); 

    //You may not know this, but NSUserDefaults can be used to parse command line arguments! 
    //in this case, the arguments are passed in like this: 
    // -fullMomPath /hd/some/path/file.mom -fullStorePath /hd/some/path/file.sql 
    //by passing in the storePath, the calling script knows where the sqlite file will be and can copy it to the resulting application bundle 
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults]; 
    NSString *momPath = [args stringForKey:@"fullMomPath"]; 
    NSString *storePath = [args stringForKey:@"fullStorePath"]; 

    // Create the managed object context 
    NSManagedObjectContext *context = managedObjectContext(momPath, storePath); 


    //build and save your NSManagedObjects here 
    //in my case, i parse some plist files and create GroceryList type stuff, but whatever you do is your business. 

    return 0; 
} 

NSManagedObjectModel *managedObjectModel(NSString* momPath) { 

    static NSManagedObjectModel *model = nil; 

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

    NSURL *modelURL = [NSURL fileURLWithPath:momPath]; 
    model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 

    return model; 
} 



NSManagedObjectContext *managedObjectContext(NSString* momPath, NSString* storePath) { 

    static NSManagedObjectContext *context = nil; 
    if (context != nil) { 
     return context; 
    } 

    context = [[NSManagedObjectContext alloc] init]; 

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel(momPath)]; 
    [context setPersistentStoreCoordinator: coordinator]; 

    NSString *STORE_TYPE = NSSQLiteStoreType; 

    NSURL *url = [NSURL fileURLWithPath:storePath]; 

    NSError *error; 
    NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:&error]; 

    if (newStore == nil) { 
     NSLog(@"Store Configuration Failure\n%@", 
       ([error localizedDescription] != nil) ? 
       [error localizedDescription] : @"Unknown Error"); 
    } 

    return context; 
} 
+0

¡Ey gracias por compartir! Sin embargo, estoy teniendo problemas para determinar el camino de MOM. Ver http://stackoverflow.com/questions/4600312/how-to-get-path-of-momd-file-in-core-data ¡Gracias! – Stunner

Cuestiones relacionadas