cocoaheads toulouse - getting to the core of core data
TRANSCRIPT
Introduction à CoreData
Partie 1
Jérome AlvesRomain BricheMichel Moreau
Partie 1
• Présentation des concepts
• Intégration
• Modélisation
• Utilisation basique
Partie 11
• Concepts avancés
• Contextes multi-thread
• Migrations
• Performance
Introduction
Introduction
• Qu’est-ce que CoreData
• Framework de gestion de persistance
Introduction
• Qu’est-ce que CoreData
• Framework de gestion de persistance
• Techniques de gestion de persistance
• Fichiers
• Property List
• SQL
Eléments fondamentaux
Eléments fondamentaux
Entités
Eléments fondamentaux
EntitésAttributs
Eléments fondamentaux
Entités
Relations
Attributs
Types de données
non-persistant persistant
Type de base NSObject NSManagedObject
Attributs * * (mais c’est compliqué)
Méthodes * *
La pile CoreData
La pile CoreData
Managed Object Model
A collection of entity descriptions
La pile CoreDataManaged Object Context
A collection of managed objects
Managed Object Model
A collection of entity descriptions
La pile CoreDataManaged Object Context
A collection of managed objects
Managed Object Model
A collection of entity descriptions
Persistent Store Coordinator
A collection of stores
La pile CoreDataManaged Object Context
A collection of managed objects
Managed Object Model
A collection of entity descriptions
Persistent Store Coordinator
A collection of stores
Persistent Object Store
A collection of object data
La pile CoreDataManaged Object Context
A collection of managed objects
Managed Object Model
A collection of entity descriptions
Persistent Store Coordinator
A collection of stores
Persistent Object Store
A collection of object data
Store File
La pile CoreData
Core Data vs MVC
Model
Controller View
CoreData
Core Data vs MVC
Model
Controller View
Mo
de
l
CoreData
Core Data vs MVC
Model
Controller View
Mo
de
l
CoreData
Core Data vs MVC
Model
Controller View
Cloud
Création du modèle
Fichier .xcdatamodel
Le Model Editor
Création d’entités
Créations d’attributs
Types d’attributs
‣Non défini‣Entiers‣Décimal- plus précis‣Double‣Flottant
‣Chaîne de caractères‣Booléen‣Date‣Binaire‣Transformable
Propriétés‣Optionnel‣Transcient- non persisté- requiert accesseurs- mofications observables- migration facile‣Indexé- performance
Relations
Relations inverses
Règles de suppression
‣Pas d’action‣Nullité‣Cascade‣Déni- impossible de supprimé si la relation existe encore
Propriétés avancées
‣Fetched properties‣Fetch requets
Et maintenant?
Exemple d’utilisation// Créer de la requêteNSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];[request setEntity:[NSEntityDescription entityForName:@"Enfant" inManagedObjectContext:moc]];
// Récupération d’un objetNSError *error = nil;NSManagedObject *enfant = [[moc executeFetchRequest:request error:&error] lastObject];[request release];
// Création d’un objet if (!enfant) { enfant = [NSEntityDescription insertNewObjectForEntityForName:@"Enfant" inManagedObjectContext:moc];}
// Passage de valeur[enfant setValue:@"Harry" forKey:@"prenom"];[enfant setValue:@"Potter" forKey:@"nom"];
KVC‣Accès “générique” à un attribut d’un objet- exemple: attribut “prenom” de l’objet “enfant”‣Binding pendant le Runtime- nom de l’attribut non connu au moment de la compilation- Erreur “Unknown value for key ...”‣Logique- Cherche pour un accesseur- Cherche pour une variable- Cherche valueForUndefinedKey:/setValueForUndefinedKey:‣Compatibilité- OBJ-C 2.0 @property/@synthesize
KVO
‣Notifications- exemple: changement de la valeur d’un attribut‣Méthodes- willAccessValueForKey: / didAccessValueForKey:- willChangeValueForKey: / didChangeValueForKey:- ...
KVO/KVC
‣NSObject -> OK‣NSManagedObject -> !OK
Intérêt Sous-Classe
‣Compatible KVC- prenom- setPrenom:- ...‣Création de classes personnalisées- nomComplet- ...
Sous-classes
Sous-classes
Header
@class Parent;
@interface Enfant : NSManagedObject {@private// Pas de variables}@property (nonatomic, retain) NSString * nom;@property (nonatomic, retain) NSString * prenom;@property (nonatomic, retain) NSDate * dateNaissance;@property (nonatomic, retain) NSSet* parents;
@end
Implementation#import "Enfant.h"#import "Parent.h"
@implementation Enfant@dynamic nom, prenom, dateNaissance, parents;
- (void)addParentsObject:(Parent *)value { NSSet *changedObjects = [[NSSet alloc] initWithObjects:&value count:1]; [self willChangeValueForKey:@"parents" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [[self primitiveValueForKey:@"parents"] addObject:value]; [self didChangeValueForKey:@"parents" withSetMutation:NSKeyValueUnionSetMutation usingObjects:changedObjects]; [changedObjects release];}
- (void)removeParentsObject:(Parent *)value {...}- (void)addParents:(NSSet *)value {...}- (void)removeParents:(NSSet *)value {...}
@end
Sous-classes
Exemple d’utilisation// Créer de la requêteNSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];[request setEntity:[NSEntityDescription entityForName:@"Enfant" inManagedObjectContext:moc]];
// Récupération d’un objetNSError *error = nil;Enfant *enfant = [[moc executeFetchRequest:request error:&error] lastObject];[request release];
// Création d’un objet if (!enfant) { enfant = [NSEntityDescription insertNewObjectForEntityForName:@"Enfant" inManagedObjectContext:moc];}
// Passage de valeur[enfant setPrenom:@"Harry"];[enfant setNom:@"Potter"];
NE PAS “OVERRIDER”
‣-init- ne fonctionne pas comme -init de NSObject- modifie la structure mais les données sont absentes‣-dealloc- Ne se produit pas quand espéré- Core Data “gère la gestion mémoire” au sein de la classe
ALTERNATIVES
‣-awakeFromInsert- lors de la création- appelée 1 seule et unique fois‣-awakeFromFetch- appelée à chaque fois que l’objet est retourné (non créé)‣-willTurnIntoFault- appelée lors que l’objet est réellement détruit‣...- voir la documentation
Attention à la modification du modèle
Démo
Opérations de base
• Ajouter un élément
• Supprimer un élément
• Créer une requête
• Prédicat
• Sort Descriptor
• Sauvegarde
Insertion d’élément
// Demande de création d’un managedObject au contexte, dans une entité précise
Event *event = (Event *)[NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectContext];
Suppression d’élément// Obtenir l’objet a supprimerNSManagedObject *eventToDelete = [eventsArray objectAtIndex:indexPath.row];
// Demande de suppresion au contexte[managedObjectContext deleteObject:eventToDelete];
Les requêtes
• Une requête :
• Un prédicat
• Un sortDescriptor
• Execution
Requête
Les requêtes
Requête
Les requêtes
Prédicat
Requête
Les requêtes
Prédicat
Requête
Les requêtes
Prédicat
SortDescriptor
Requête
Les requêtes
Prédicat
SortDescriptorSortDescriptorSortDescriptorSortDescriptorSortDescriptor
Requête
Les requêtes
Prédicat
SortDescriptorSortDescriptorSortDescriptorSortDescriptorSortDescriptor
Requête
Les requêtes
Prédicat
SortDescriptorSortDescriptorSortDescriptorSortDescriptorSortDescriptor
Entité
Requête
Les requêtes
Prédicat
SortDescriptorSortDescriptorSortDescriptorSortDescriptorSortDescriptor
Entité
Les requêtes
// Créer de la requêteNSFetchRequest *request = [[NSFetchRequest alloc] init];
// Obtenir l’entitéNSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Créer un prédicatNSPredicate *predicate = [NSPredicate predicateWithFormat: @"(lastName LIKE[c] 'Worsley') AND (salary > %@)", minimumSalary];
[request setPredicate:predicate];
Les requêtes// Créer un sortDescriptorNSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey: @"creationDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];[sortDescriptor release];
// Exécuter la requêteNSError *error = nil;NSArray *array = [moc executeFetchRequest:request error:&error];
if (array == nil){ // Deal with error...}
Sauvegarde du contexte
Managed Object Context
Managed Object ModelPersistent Store Coordinator
Persistent Object Store
MOMO
MOMO
MO
Store File
Sauvegarde du contexte
Managed Object Context
Managed Object ModelPersistent Store Coordinator
Persistent Object Store
MOMOMOMOMO
Store File
Sauvegarde du contexte
// NSError *error = nil;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
Démo
NSFetchedResultsController‣Seulement pour iOS- Pas (encore) sur Mac‣Observations des changements- Notifie le contrôleur qu’il doit rafraîchir l’UI- Notifications sélectives => meilleure performance- Objets/propriétés‣-willTurnIntoFault- appelée lors que l’objet est réellement détruit‣...- voir la documentation
Trève de blabla
@interface ViewController : UITableViewController <NSFetchedResultsControllerDelegate> {" NSFetchedResultsController *fetchedResultsController;" NSManagedObjectContext *moc;}
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;@property (nonatomic, retain) NSManagedObjectContext *moc;
- (NSFetchedResultsController*)fetchedResultsController { if (_fetchedResultsController) return _fetchedResultsController; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Enfant" inManagedObjectContext:[self moc]]; [fetchRequest setEntity:entity]; [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"nom==%@",@"Potter"]]; [fetchRequest setFetchBatchSize:20]; NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"prenom" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil]; [fetchRequest setSortDescriptors:sortDescriptors]; NSFetchedResultsController *frc = nil; frc = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self moc] sectionNameKeyPath:nil cacheName:@"Potter"]; [frc setDelegate:self]; [self setFetchedResultsController:frc]; [frc release], frc = nil; [fetchRequest release], fetchRequest = nil; [sortDescriptor release], sortDescriptor = nil; [sortDescriptors release], sortDescriptors = nil; return _fetchedResultsController;}
NSFetchedResultsControllerDelegate
‣ -controllerWillChangeContent: ‣ -controller:didChangeSection:atIndex:forChangeType:‣ -controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:‣ -controllerDidChangeContent:
NSFetchedResultsControllerDelegate
Pour aller plus loin
‣Les opérations- @sum, @distincUnionOfSets, etc...‣Les migrations- automatique, mapping model, manuelle‣Notions avancées- multi-threading, données binaire, faulting, synchronisation‣Performance‣Nouveautés iOS5- iCloud, concurrence, protection, …
Suggestions de ressources
Nouveautés iOS5iCloud, concurrence, protection, …
Merci