2010-01-31 20 views
5

Estoy en proceso de (finalmente) cargar mi aplicación en un dispositivo iPhone para realizar pruebas. Hasta ahora solo he probado la aplicación en el simulador. La aplicación está centrada en datos y utiliza una base de datos SQLite. Creé una base de datos SQLite apropiada con datos de muestra que utilicé en el simulador. ¿Cómo puedo copiar este archivo .sqlite3 en el iPhone?Copia de datos en la carpeta de datos de la aplicación en el iPhone

Esto era fácil con el simulador como acabo podría copiar el archivo .sqlite3 en el soporte ~/Library/Application Support/simulador de iPhone/usuario/Aplicaciones/{UUID}/Documentos carpeta, pero no puedo encontrar la manera para obtener esto en la misma ubicación en el dispositivo de iPhone real. Volver a crear la base de datos desde cero en el teléfono no es realmente una opción, ya que ya he hecho todos los trabajos difíciles creando la base de datos en la Mac.

Respuesta

6

¿Por qué no agregarlo a su paquete de aplicaciones? Haga clic derecho en la carpeta Resources en su ventana de proyecto en Xcode, luego seleccione Add>Existing Files... para agregar su base de datos sqlite.

A continuación, cargar el archivo del paquete de aplicación:

NSString *databasePath = [[NSBundle mainBundle] pathForResource:@"mySQLiteDatabaseFile" ofType:@"sqlite3"]; 
NSData *databaseData = [NSData dataWithContentsOfFile:databasePath]; 
// ... 
+0

Gracias Alex. ¿Pero puedo volver a escribir en la base de datos si se ha incluido en el paquete de la aplicación? – Skoota

+2

No, pero puede copiar esta base de datos básica "preinicializada" desde allí a la carpeta 'Documentos', que es grabable. Lo bueno es que este enfoque también permite al usuario "restablecer" la aplicación. –

+0

Gracias Alex. Ese es un muy buen enfoque. – Skoota

11

Como dijo Alex, hay que añadir el archivo de base de datos como un recurso para su proyecto. Esto le indicará a Xcode que agrupe su archivo de base de datos en su .app. Sin embargo, ese archivo es de solo lectura, depende de usted copiarlo a su carpeta de documentos de aplicaciones (en el dispositivo o simulador, lo mismo), donde se puede escribir básicamente.

Aquí está el código que utilizo para este tipo de cosas a continuación. Lo bueno de este código es que actualizará automáticamente la copia de escritura en su carpeta de documentos de aplicaciones cada vez que cambie la copia "principal" incluida en .app. Use 'pathLocal' para abrir su base de datos (escribible) ...

La función a continuación retorna SÍ cuando la operación fue exitosa (si se necesitó o no una copia). Usted es libre de cambiar eso con lo que más le convenga :)

NSString *pathLocal, *pathBundle; 

// Automatically copy DB from .app bundle to device document folder if needed 
- (BOOL)automaticallyCopyDatabase { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES); 
    NSString *documentsDir = [paths objectAtIndex:0]; 
    pathLocal = [documentsDir stringByAppendingPathComponent:@"mydb.sqlite"]; 
    pathBundle = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"mydb.sqlite"]; 

    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSDictionary *localAttr = [fileManager fileAttributesAtPath:pathLocal traverseLink:YES]; 
    BOOL needsCopy = NO; 
    if (localAttr == nil) { 
     needsCopy = YES; 
    } else { 
     NSDate *localDate; 
     NSDate *appDBDate; 
     if (localDate = [localAttr objectForKey:NSFileModificationDate]) { 
      NSDictionary *appDBAttr = [fileManager fileAttributesAtPath:pathBundle traverseLink:YES]; 
      appDBDate = [appDBAttr objectForKey:NSFileModificationDate]; 
      needsCopy = [appDBDate compare:localDate] == NSOrderedDescending; 
     } else { 
      needsCopy = YES; 
     } 
    } 
    if (needsCopy) { 
     NSError *error; 
     BOOL success; 
     if (localAttr != nil) { 
      success = [fileManager removeItemAtPath:pathLocal error:&error]; 
     } 
     success = [fileManager copyItemAtPath:pathBundle toPath:pathLocal error:&error]; 
     return success; 
    } 
    return YES; 
} 
+0

Eso es fantástico. Gracias por este código Zoran. Hará las cosas un poco (es decir, mucho) más fáciles para mí :) Particularmente me gusta que el código refresque la copia grabable cuando la copia principal cambie. – Skoota

0

aquí cómo he hecho esto crear una clase llamada DBManagement y en m archivo de implementar estas methods.also poner esta línea en el archivo de aplicación por encima de la línea @implementation

static sqlite3 * CHManagement = nil;

-(NSString *) getDBPath 
{ 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/CHManagement.sqlite"]; 
    return MyDatabasePath; 

} 

-(void) checkDataBase 
{ 
NSLog(@"CheckDatabase Called"); 
NSFileManager *fileManager=[NSFileManager defaultManager]; 
NSError *error=[[[NSError alloc]init] autorelease]; 
NSString *dbPath = [self getDBPath]; 
BOOL success=[fileManager fileExistsAtPath:dbPath]; 
if(!success) 
{ 
NSString *defaultDBPath=nil; 
defaultDBPath=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"CHManagement.sqlite"]; 
success=[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error]; 
if(!success) 
{ 
    NSAssert1(0,@"failed to create database with message '%@'.",[error localizedDescription]); 
    } 
} 
else 
{ 
sqlite3 *MyDatabase; 
NSInteger VersionNumber=0; 
sqlite3_stmt *CompiledStatement=nil; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/CHManagement.sqlite"]; 
if(sqlite3_open([MyDatabasePath UTF8String],&MyDatabase) == SQLITE_OK) 
{ 
    sqlite3_prepare_v2(MyDatabase, "select appVersionNo from VersionInfo", -1, &CompiledStatement, NULL); 
    while(sqlite3_step(CompiledStatement) == SQLITE_ROW) 
    { 
    VersionNumber=sqlite3_column_int(CompiledStatement,0); 
    } 
    sqlite3_reset(CompiledStatement); 
    sqlite3_finalize(CompiledStatement); 
    sqlite3_close(MyDatabase); 
} 
if (VersionNumber!=1) 
{ 
    [self deleteDatabase]; 
    NSString *defaultDBPath=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"CHManagement.sqlite"]; 
    success=[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error]; 
    if(!success) 
    { 
    NSAssert1(0,@"failed to create database with message '%@'.",[error localizedDescription]); 
    } 
    } 
} 
} 

- (void)deleteDatabase 
{ 
NSLog(@"Delete Database Called"); 
NSError **error=nil; 
NSFileManager *FileManager = [NSFileManager defaultManager]; 
NSString *databasepath = [self getDBPath]; 
    BOOL success = [FileManager fileExistsAtPath:databasepath]; 
if(success) { 
[FileManager removeItemAtPath:databasepath error:error]; 
} 
} 

con estos métodos puede cargar fácilmente la base de datos en la carpeta de documentos iphone de la aplicación. Disculpa por el formato. y appVersionNo es un campo en una tablaCalled versionInfo el valor predeterminado es 1

Cuestiones relacionadas