Bases de datos SQLite en iOS: Librería FMDB

junio 5, 2013

Muchas aplicaciones para iOS necesitan guardar datos según vamos haciendo uso de ella o ya cuentan con una base de datos inicial a la que se irán haciendo consultas. Existen varias formas de guardar información en iOS: CoreData, NSUserDefaults, bases de datos SQLite, etc. Si utilizamos bases de datos SQLite, consultar, insertar, actualizar o borrar datos se puede convertir en una tarea bastante engorrosa, “arcaica” y propensa a errores.

Para hacer consultas a SQLite desde iOS, contamos con un framework open source llamado FMDB que podemos encontrar con Github. FMDB no es más que un “ayudante” para hacernos la vida más fácil a la hora de tratar con bases de datos SQLite en aplicaciones para iPhone o iPad.

Estos son los pasos que necesitamos hacer para integrar el framework FMDB en nuestro proyecto:

1. Descargar el código fuente de FMDB desde Github.

2. Añadir los siguientes ficheros al proyecto:
– FMDatabase.h
– FMDatabase.m
– FMDatabasePool.h
– FMDatabasePool.m
– FMResultSet.h
– FMResultSet.m

3. Añadimos el framwork “libsqlite3.0.dylib” al proyecto. Para hacer esto, accedemos a los “target settings”, hacemos click en “Summary” y en la sección “Linked Frameworks and Libraries” pulsamos en el botón “+” para añadir un nuevo framework al proyecto. Buscamos “libsqlite3.0.dylib” y aceptamos.

4. En el controlador donde queramos hacer consultas a la base de datos SQLite, deberemos importar estas dos cabeceras:
#import “sqlite3.h”
#import “FMDatabase.h”

5. Y listo, ya podemos empezar 😉
 

Crear una nueva tabla

1
2
3
4
5
6
7
8
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [docPaths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"mibasededatos.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
[database executeUpdate:@"CREATE TABLE usuarios (id INTEGER PRIMARY KEY DEFAULT NULL, nombre TEXT DEFAULT NULL, apellido TEXT DEFAULT NULL, edad INTEGER DEFAULT NULL)"];
[database close];

En las líneas 1-6 indicamos la ruta de nuestro fichero de base de datos (“mibasededatos.sqlite” en este ejemplo) y la abrimos para poder trabajar con ella.

La base de datos es creada y guardada en directorio Documents. En iOS solo puedes crear, actualizar, borrar o insertar datos en una base de datos que se encuentre en la carpeta Documents. Si solo quieres consultar datos (y no modificarlos), puedes crear la base de datos en cualquier lugar del proyecto. Si la aplicación cuenta con una base de datos ya existente, la tienes que copiar al directorio Documents.

Para trabajar con bases de datos SQLite desde nuestro Mac, recomiendo la aplicación SQLite Database Browser (gracias a @sloy5101 por la recomendación).

Es muy importante que no nos olvidemos de cerrar la conexión a la base de datos como podemos ver en la línea 8.
 

Realizar consultas a la base de datos

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [docPaths objectAtIndex:0];
NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"mibasededatos.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
FMResultSet *results = [database executeQuery:@"SELECT * FROM usuarios"];
// Podemos utilizar variables en las consultas
// FMResultSet *results = [database executeQuery:@"SELECT * FROM usuarios WHERE name = ?", @"Jon"];
while([results next]) {
    NSLog(@"Id: %d", [results intForColumn:@"id"]);
    NSLog(@"Nombre: %@", [results stringForColumn:@"nombre"]);
    NSLog(@"Apellido: %@", [results stringForColumn:@"apellido"]);
    NSLog(@"Edad: %d", [results intForColumn:@"edad"]);
}
[database close];

FMDB nos ofrece diferentes métodos para obtener el tipo de dato correcto y evitar posibles errores:

– intForColumn:
– longForColumn:
– longLongIntForColumn:
– boolForColumn:
– doubleForColumn:
– stringForColumn:
– dateForColumn:
– dataForColumn:
– dataNoCopyForColumn:
– UTF8StringForColumnIndex:
– objectForColumn:
 

Insertar datos en una tabla

1
2
3
4
5
6
7
8
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [docPaths objectAtIndex:0];
NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"mibasededatos.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
[database executeUpdate:@"INSERT INTO usuarios (id, nombre, apellido, edad) VALUES (?, ?, ?, ?)", [NSNumber numberWithInt:1], @"Jon", @"Segador", [NSNumber numberWithInt:29], nil];
[database close];

Lo único a tener en cuenta para insertar datos en una tabla con el método executeUpdate: (en realidad, para cualquier método que acepte parámetros), es que deben ser objetos.
 

Actualizar datos

1
2
3
4
5
6
7
8
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [docPaths objectAtIndex:0];
NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"mibasededatos.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
[database executeUpdate:@"UPDATE usuarios SET nombre = ? WHERE id = ?", @"Luis", [NSNumber numberWithInt:1], nil];
[database close];

 

Borrar registros de la base de datos

1
2
3
4
5
6
7
8
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *dbPath = [documentsDir   stringByAppendingPathComponent:@"mibasededatos.sqlite"];
 
FMDatabase *database = [FMDatabase databaseWithPath:dbPath];
[database open];
[database executeUpdate:@"DELETE FROM usuarios WHERE id = ?", [NSNumber numberWithInt:1], nil];
[database close];
CompartirTweet about this on TwitterShare on TumblrShare on FacebookShare on LinkedInShare on Google+Email this to someone

Tags ; , , , , , , , ,

Escribe un comentario

Los comentarios son moderados y se utiliza rel="nofollow" para los enlaces.