Core Data : introduction

jeudi 15 novembre 2012

Aujourd’hui, je me suis attelé à la mise en place dans mon application d’une gestion de base de données avec Core Data.
Pas évident à inclure dans un projet existant.

Voici ma procédure:

  • 1. Tout d’abord, faire un ajout de fichier de type Core Data > Data Model, avec ce fichier de type .xcdatamodeld on a accès à une interface de gestion de base de donnée dans l’interface builder.
  • 2. On créé une « entity » qui correspond à notre base de données et on y ajoute nos attributs nécessaire à notre entité ainsi que les relations entre les attributs d’entités différentes.
  • 3. Ensuite, on va générer un fichier class qui va refléter notre entité en objet, et c’est l’interface builder qui le fait pour nous en cliquant sur new file Core Data > NSManagedObject subclass et il nous demande quel entité à générer.
  • 4. Et pour pouvoir utiliser la base de donnée dans plusieurs vues, j’ai rajouté les codes suivants dans Appdelegate: AppDelegate.h
#import <QuartzCore/QuartzCore.h>
#import "Barcode.h"

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (NSURL *)applicationDocumentsDirectory;
+ (UCHAppDelegate *)sharedAppDelegate;

La fonction « sharedAppDelegate » permet de récupérer le Appdelegate dans les autres vues et donc les objets nécessaires pour récupérer des données.

AppDelegate.m

#pragma mark - Core Data stack
+ (UCHAppDelegate *)sharedAppDelegate
{
    return (UCHAppDelegate *) [UIApplication sharedApplication].delegate;
}
/**
 Returns the managed object context for the application.
 If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
 */
- (NSManagedObjectContext *)managedObjectContext
{
    if (__managedObjectContext != nil)
    {
        return __managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil)
    {
        __managedObjectContext = [[NSManagedObjectContext alloc] init];
        [__managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return __managedObjectContext;
}

/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created from the application's model.
 */
- (NSManagedObjectModel *)managedObjectModel
{
    if (__managedObjectModel != nil)
    {
        return __managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"XXXX" withExtension:@"momd"];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return __managedObjectModel;
}
/**
 Returns the persistent store coordinator for the application.
 If the coordinator doesn't already exist, it is created and the application's store added to it.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (__persistentStoreCoordinator != nil)
    {
        return __persistentStoreCoordinator;
    }
    
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"XXXX.sqlite"];
    
    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
    
    return __persistentStoreCoordinator;
}

#pragma mark - Application's Documents directory

/*
 Returns the URL to the application's Documents directory.
 */
- (NSURL *)applicationDocumentsDirectory
{
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}

Il faut remplacer le XXXX par le nom du fichier .xcdatamodeld.
Voilà maintenant, elle est accessible dans toute votre application en utilisant ceci dans le .h de votre vue:

#import "UCHAppDelegate.h"

@property (nonatomic, retain)  NSManagedObjectContext *context;

Maintenant pour récupérer les records de l’entité:

    // on récupère le context
    context = [[UCHAppDelegate sharedAppDelegate] managedObjectContext];
    // On récupère l'entité
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Barcode" inManagedObjectContext:context];
    // On créé une requête pour cette entité
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    // qu'on lui assigne
    [request setEntity:entity];
    // on créé un sort
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
    [request setSortDescriptors:sortDescriptors];
    // on exécute la requête à l'entité
    NSError *error;
    // Tout est mis dans un tableau 
    shopsCard = [[context executeFetchRequest:request error:&error] mutableCopy];
    if (!shopsCard) {
        // Handle the error.
        // This is a serious error and should advise the user to restart the application
    }

Pour insérer un record à une entité:

    // on récupère le context
    context = [[UCHAppDelegate sharedAppDelegate] managedObjectContext];
    // On récupère notre objet qui représente notre entité
    Barcode *barcode = (Barcode *)[NSEntityDescription insertNewObjectForEntityForName:@"Barcode" inManagedObjectContext:context];
    // on assigne nos valeur
    barcode.codebar = str;
    barcode.name = @"test";

    NSError *error;
    // SAUVEGARDE
    if(![context save:&error]){
        NSLog(@"Error");
    }

Pour supprimer un record d’une entité:

         // On créé un objet entité en récupérant l'objet dans un tableau (uitableview)
         Barcode *barcode = [shopsCard objectAtIndex:indexPath.row];
        // On retire l'objet du context
        [context deleteObject:barcode];
        NSError *error;
        // On sauve les changements
        [context save:&error];
        // ON retire aussi de la liste
        [shopsCard removeObjectAtIndex:indexPath.row];
        // On rafraîchit la liste
        [self.tableView reloadData];

Pour plus d’informations voici le tutoriel que j’ai suivi: cliquez ici

Attention:Tout changement de structure du model Core Data après qu’il soit installé sur un iphone ou le simulateur, il faut de temps en temps supprimer l’application et l’installer complètement car l’ancienne structure risque de rester en cache. Et vous obtientré une erreur dont la raison est : « The model used to open the store is incompatible with the one used to create the store ».

Tags: Core Data , Développement , IOS , Objective C , Xcode