abr 30

Core Data nos simplifica mucho el trabajo cuando queremos trabajar con una base de datos ya que tiene implementadas muchas de las tareas comunes asociadas al ciclo de vida de objetos. En este post no quiero dar una guía sobre Core Data, simplemente un ejemplo de como manejar, desde nuestra aplicación, los elementos mínimos requeridos para trabajar con Core Data y así tener una base con la que empezar a usar este Framework. En la documentación de Apple encontrareis muchísima información al respecto (Core Data Programming Guide).

Para empezar necesitamos tres objetos diferentes, un NSManagedObjectModel, un NSManagedObjectContext y un NSPersistentStoreCoordinator.
El primero es el que contiene la información que describe el modelo de nuestra base de datos, las entidades y sus atributos así como relaciones entre ellas… El segundo se ocupa de controlar un conjunto de objetos, entidades de nuestra base de datos, vigilando los cambios que se realizan sobre ellos, dando la opción de deshacer cambios y validación de estos entre otras funciones, finalmente el tercero nos hace de enlace entre el segundo y la base de datos física, guardando los posibles cambios realizados en el contexto.

Cuando creamos un nuevo proyecto en XCode, en algunas plantillas, nos da la opción de usar Core Data,

si marcamos la casilla indicada, XCode nos creará el proyecto y en nuestro AppDelegate tendremos tres variables, los tres objetos mencionados anteriormente.

@interface TestAppDelegate : NSObject <UIApplicationDelegate> {
 
    NSManagedObjectModel *managedObjectModel;
    NSManagedObjectContext *managedObjectContext;	    
    NSPersistentStoreCoordinator *persistentStoreCoordinator;
 
    UIWindow *window;
}
 
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
 
@property (nonatomic, retain) IBOutlet UIWindow *window;
 
- (NSString *)applicationDocumentsDirectory;
 
@end

Si miramos en el grupo “Resources” de nuestro proyecto, veremos un archivo con extensión “.xcdatamodel”, es aquí donde creamos las entidades de nuestra base de datos con sus atributos y relaciones.

Ahora bien, alguno se estará preguntando como realizamos búsquedas en nuestra base de datos, para mostrar información en una vista, o para llenar una tabla. Para eso necesitamos una cuarta clase, NSFetchRequest.

Si queremos centralizar las consultas sobre la base de datos en un solo objeto de nuestra aplicación y evitar tener que ir pasando estos cuatro elementos, os recomiendo lo siguiente. En nuestro AppDelegate añadimos las siguientes funciones:

// Returns the AppDelegate (self) so it is accesible from all classes
+ (TestAppDelegate *)sharedAppDelegate;
 
// Methods for fetching data from the data store
- (NSArray *)allObjectsForEntity:(NSString *)entity orderedBy:(NSString *)atribute;

La función de clase nos devolverá el AppDelegate (si mismo), de manera que a través de él podamos acceder a los tres objetos que nos controlan la base da datos, para que no sea posible crear más de un AppDelegate y éste no pueda ser modificado lo que haremos será crearnos una variable estática, y la inicializaremos en nuestro init, en el AppDelegate.m añadimos

static TestAppDelegate *sharedInstance;
 
@implementation TestAppDelegate
 
- (id) init
{
	if (sharedInstance) {
		NSLog(@"Error: You are creating a second AppController");
	}
 
	self = [super init];
	if (self != nil) {
		sharedInstance = self;
	}
	return self;
}
 
...
 
/**
 Returns itself for easy acces to the appController
 */
+ (TestAppDelegate *) sharedAppDelegate {
	return sharedInstance;
}

mientras que la función de instancia, será la encargada de hacer la búsqueda.

/**
 Returns an array with all the objects for the given entity name sorted by the given atribute
 */
- (NSArray *)allObjectsForEntity:(NSString *)entity orderedBy:(NSString *)atribute {
	/*
	 Set up the fetched results controller.
	 */
	// Create the fetch request for the entity.
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	// Edit the entity name as appropriate.
	NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entity 
                                                             inManagedObjectContext:[self appManagedObjectContext]];
	[fetchRequest setEntity:entityDescription];
 
	// Set the batch size to a suitable number.
	//[fetchRequest setFetchBatchSize:20];
 
	// Edit the sort key as appropriate.
	NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:atribute ascending:YES];
	NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
 
	[fetchRequest setSortDescriptors:sortDescriptors];
 
	// Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
	NSError *error;
	NSArray *result = [[self appManagedObjectContext] executeFetchRequest:fetchRequest error:&error];
	if (error) {
		// TODO: Manage error executing fetch
		[error release];
	}
 
	[fetchRequest release];
	[sortDescriptor release];
	[sortDescriptors release];
	return result;
}

esta función nos devuelve un array con todos los objetos del tipo que le hemos indicado “entity” ordenados ascendentemente por el “atribute” indicado, con este array ya podemos obtener la información que queramos mostrar, o llenar una tabla. Tened en cuenta que este array esta lleno de NSManagedObject, y que hay que usar la función valueForKey: para obtener el valor de cada atributo.

Usando de base esta última función, podemos añadir a nuestro AppDelegate otras funciones para realizar otro tipo de búsquedas según nos sea necesario y centralizar así, la interacción con la base de datos en nuestro AppDelegate.

Por ejemplo, en otra clase que requiera información de la base de datos, podemos inicializar un vector de datos en la función “viewDidLoad” de la siguiente manera.

- (void)viewDidLoad {
    [super viewDidLoad];
   TestAppDelegate *appDelegate = [TestAppDelegate sharedAppDelegate];
   NSArray *dataArray = [appDelegate allObjectsForEntity:@"Test" orderedBy:@"date"];	
}

Espero que os sea de utilidad para empezar a usar Core Data, aunque solo sea una forma muy básica de hacerlo.

VN:F [1.9.8_1114]
Rating: 4.5/5 (4 votes cast)
VN:F [1.9.8_1114]
Rating: +3 (from 5 votes)
Tagged with:
preload preload preload