Persistencia en nuestra iPhone App
En el anterior post os comenté sobre como guardar datos de configuración con [NSUserDefaults standardUserDefaults], muy útil si queréis guardar algún dato pequeño o si el usuario no es la primera vez que visita una pestaña, pero siempre algún dato que no nos haga falta buscar sobre él. En el momento que queráis que vuestra app tenga Favoritos, ultimos visitados o frecuentes, debéis ayudaros de una base de datos, para poder realizar consultas rápidas.
Como sabéis, nuestro iPhone posee bastantes librerías, y algunas de ellas nos ayudan a gestionar BBDD del tipo SQLite3 (como libsqlite3.0.dylib y algunas más) que si bien están limitadas por Apple y no tienen todas las extensiones que nos gustaría, podemos gestionar nuestra base de datos sencillamente (o eso parecía). En la aplicación que estoy desarrollando, necesitaba incluir una pestaña de Favoritos, y tuve que empaparme de SQLite3. Primero me baje este add-on para Firefox, SQLite Manager, y me descargue el Sample Code de Apple, SQLite Books, que nos enseña como introducir, recuperar y borrar datos de una base de datos. Me dedique a observar el ejemplo, y me pareció lo mas cercano a un infierno, hay que realizar muchísimas operaciones iguales bastantes veces, hidratar y deshidratar los datos, después de cada inserción o borrado. Para muestra, os enseño como borrar un elemento
- (void)deleteFromDatabase {
// Compile the delete statement if needed.
if (delete_statement == nil) {
const char *sql = "DELETE FROM book WHERE pk=?";
if (sqlite3_prepare_v2(database, sql, -1, &delete_statement, NULL) != SQLITE_OK) {
NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
}
// Bind the primary key variable.
sqlite3_bind_int(delete_statement, 1, primaryKey);
// Execute the query.
int success = sqlite3_step(delete_statement);
// Reset the statement for future use.
sqlite3_reset(delete_statement);
// Handle errors.
if (success != SQLITE_DONE) {
NSAssert1(0, @"Error: failed to delete from database with message '%s'.", sqlite3_errmsg(database));
}
}
Pensé que no podía ser verdad, y debía haber una solución, algún FrameWork que utilizará el patrón Fachada para quitarme este banco de posibles errores de en medio. Buscando un poco encontré FMDB y aqui teneis varios ejemplos de uso.
Para mi proyecto, me he creado un DataBaseController, que hace de fachada sobre el wrapper FMDB, teniendo metodos para la insercion, borrado y consulta e internamente realizo los accesos al framework.
Aqui os enseño alguno ejemplos
[self.db executeUpdate:@"delete from borneta where numero=?" ,
borneta.numero];
// Devuelve el array de favoritos
- (NSMutableArray *) devuelveFavoritos
{
NSMutableArray *arrayRetornoFavoritos=[[NSMutableArray alloc] init];
FMResultSet *rs = [self.db executeQuery:@"select * from borneta order by id ASC"];
while ([rs next]) {
Borneta *borneta = [[Borneta alloc] init];
borneta.nombre=[rs stringForColumn:@"nombre"];
borneta.direccion=[rs stringForColumn:@"direccion"];
borneta.numero=[rs stringForColumn:@"numero"];
borneta.numero=[rs stringForColumn:@"numero"];
borneta.lat=[NSNumber numberWithDouble:[rs doubleForColumn:@"lat"]];
borneta.lng=[NSNumber numberWithDouble:[rs doubleForColumn:@"lng"]];
[arrayRetornoFavoritos addObject:borneta];
}
return arrayRetornoFavoritos;
}
Tengo que decir, que me ha resultado muy cómodo tirar de este wrapper que atacar directamente a la libreria de sqlite, por lo que os recomiendo que le deis una oportunidad, si veis que el ejemplo de Apple no os aclara mucho.
Si tenéis alguna pregunta de como utilizar FMDB o cualquier consulta sobre programación en Cocoa, aquí me tenéis.
Posteado en Uncategorized