• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

T#081 – Guida all’uso di Core Data (Parte 1)

By doppioslash | on 6 Dicembre 2010 | 14 Comments
Senza categoria

t081-usare-core-data-iphone-ipad-00 Ciao, sono Claudia e in questo mio primo articolo su devapp.it vi parlerò di Core Data.

1. Cos’è e cosa non è Core Data

L’esatta definizione della natura di Core Data è di solito l’oggetto di complesse perifrasi, viene di volta in volta frainteso e considerato un ORM o un database.
La documentazione Apple lo definisce come un framework che gestisce la persistenza dei dati e il grafo degli oggetti, che prende concetti dal mondo dei database per portare la gestione dei dati nelle applicazioni a nuovi livelli.
In pratica Core Data è per il Model ciò che Interface Builder è per il View, non si occupa solo della persistenza, ma anche di gestire i dati in memoria, del passaggio da una versione all’altra e dell’undo.
Sia iTunes che apple.com sono ospitati su un server Web Objects, tecnologia da cui si è evoluto il design di Core Data.

2. Considerazioni pratiche

Core Data è in grado di salvare i dati in tre diversi formati: file binario, file xml e database SQLite. Per le app iOS è di gran lunga preferibile SQLite in quanto meno avido di risorse.
Fornisce anche meccanismi per gestire gli inevitabili cambiamenti di formato nella vita dell’app.
E’ possibile aggiungere Core Data ad un’app già esistente, ne parleremo in un prossimo tutorial.

3. In questo tutorial

Costruiremo una piccola applicazione che inserisce e carica dati.
Le classi che utilizzeremo sono:

  • NSManagedObjectModel: è la classe che contiene la descrizione dei dati, Entità in Core Data, che vengono salvati nel database. Per questo useremo lo strumento grafico presente in Xcode.
  • NSManagedObjectContext: è lo stesso concetto del context di Core Graphics: è come una lavagna. I cambiamenti fatti in un contesto possono essere salvati o annullati. E’ la classe che frequenteremo di più, perché ogni volta che si vogliono ottenere, inserire o cancellare dati chiameremo i suoi metodi.
  • NSPersistentStoreCoordinator: dove si setta la path del database utilizzato dall’app, chiamato dal contesto quando registra i cambiamenti.
  • NSFetchRequest: la usiamo quando vogliamo fare ricerche nei dati. Funziona in modo simile ai comandi SQL, definiamo quale Entità vogliamo ottenere ed eventuali parametri di filtraggio.
  • NSEntityDescription: la usiamo per definire l’Entità per la Fetch Request.
  • NSPredicate: la usiamo per definire i criteri di filtraggio per la Fetch Request.
  • NSManagedObject: ogni istanza di questa classe rappresenta un’Entità. Accediamo alle sue proprietà utilizzando il Key-Value Coding. Se vogliamo accedere alle proprietà direttamente è necessario subclassare NSManagedObject, ne parleremo in un prossimo tutorial.

4. Cominciamo!

Creiamo un nuovo progetto Window-based e accertiamoci che l’opzione Use Core Data for Storage sia selezionata.
Lo chiameremo CoreDataPart1. Per non perdere tempo con codice estraneo a Core Data inseriremo l’interfaccia direttamente nell’App Delegate (non fatelo a casa!).
Apriamo MainWindow.xib e inseriamo l’interfaccia come nella figura.


L'interfaccia costruita in IB

5. Sistemiamo gli outlet

Inseriamo nell’App Delegate gli IBOutlet e le IBAction per interagire con l’interfaccia, colleghiamoli in IB e non dimentichiamo di aggiungere UITableViewDataSource alla lista dei protocolli supportati dalla classe e di collegare in IB i delegati della tableView all’AppDelegate.

Apriamo il file CoreDataPart1AppDelegate.h e aggiungiamo queste variabili d’istanza:

IBOutlet UITextField *nameField;
IBOutlet UITextField *surnameField;
IBOutlet UITextField *nickField;
IBOutlet UITableView *contattiTable;

Aggiungiamo i metodi legati ai nostri due pulsanti:

- (IBAction) showContatti;
- (IBAction) addContatto;


Gli outlet da collegare in MainWindow.xib


I delegati da collegare per la TableView in MainWindow.xib

6. Impostiamo il comportamento della tastiera – parte prima

Per fare in modo che la tastiera sparisca una volta completato l’inserimento, così da non nascondere la nostra interfaccia, dobbiamo manipolare le impostazioni degli UITextField in IB, settare come delegato l’AppDelegate, inserire UITextFieldDelegate fra la lista dei protocolli supportati nell’AppDelegate ed inserire il metodo textFieldShouldReturn: nel nostro file di implementazione:


Collegare il delegato di ogni TextField all'AppDelegate

In IB settiamo le proprietà della tastiera per ogni UITextField, per primi due sceglieremo Next come Return Key, per l’ultimo Done:


Impostazione delle proprietà della tastiera, primi due TextField


Impostazione delle proprietà della tastiera, ultimo TextField

Apriamo il file CoreDataPart1AppDelegate.m e aggiungiamo questo metodo:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
	//in questo metodo facciamo in modo che quando l'utente preme 'Next' il focus passi al prossimo campo e quando 'Done' che la tastiera sparisca
	if (textField == nameField) {
		[surnameField becomeFirstResponder];
	}
	else if (textField == surnameField) {
		[nickField becomeFirstResponder];
	}

	[textField resignFirstResponder]; 
	return YES;
}

7. Inseriamo i metodi di UITableViewDataSource

Aggiungiamo anche il codice necessario a gestire la tabella: aggiungiamo un NSArray alle variabili d’istanza e i metodi del protocollo UITableViewDataSource:

NSArray *contattiList;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
	return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return [contattiList count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	static NSString *CellIdentifier = @"Cell";
	
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle 
									   reuseIdentifier:CellIdentifier] autorelease];
    }
    // Set up the cell...
    return cell;
	
}

8. E’ il momento di Core Data!

Diamo un’occhiata al codice che il template inserisce automaticamente per noi; nell’App Delegate vediamo tre nuove variabili d’istanza, corrispondenti alle classi presentate prima, managedObjectContext, managedObjectModel e persistentStoreCoordinator. Nei loro accessori troviamo cose interessanti, come la path del database utilizzato dall’app in persistentStoreCoordinator, una volta localizzato possiamo aprirlo con qualunque utility SQLite e notarne la struttura insolita.
Inserire dati esterni in un database SQLite creato da Core Data sarà l’oggetto di un prossimo tutorial.

Procediamo nell’esplorazione del progetto, la nostra prossima tappa è il file .xcdatamodel, dove potremo definire graficamente il nostro Model.


L'editor di xcdatamodel

9. Definiamo l’Entità

Inseriamo il nostro oggetto nel box Entity, cliccando sul tasto +, modifichiamo il suo nome nel pannello all’estrema destra, chiamiamolo Contatto, la sua classe è NSManagedObject non è una classe astratta e non ha genitore.



10. E le proprietà

Nel box Property aggiungiamo 3 proprietà, utilizzando anche qui il tasto + e scegliendo Add Attribute. Cognome, Nome e Nick, sono tutte di tipo stringa non sono opzionali.


Aggiungere una proprietà con l'editor di xcdatamodel

11. E il codice dei metodi che usano Core Data

Ecco definita la nostra classe Model. Adesso andiamo ad aggiungere nel metodo addContatto il codice necessario per inserire l’oggetto nello store di Core Data.

- (IBAction) addContatto {
	//Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	
	//Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa
	NSManagedObject *contatto = [NSEntityDescription
									   insertNewObjectForEntityForName:@"Contatto" 
									   inManagedObjectContext:context];
	
	//Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'Entità appena creata
	[contatto setValue:surnameField.text forKey:@"cognome"];
	[contatto setValue:nameField.text forKey:@"nome"];
	[contatto setValue:nickField.text forKey:@"nick"];
	
	//Effettuiamo il salvataggio gestendo eventuali errori
	NSError *error;
	if (![context save:&error]) {
		NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]);
	}
}

Per visualizzare i dati andiamo ad aggiungere questo codice a showContatti:

- (IBAction) showContatti {
	//Otteniamo il puntatore al NSManagedContext
	NSManagedObjectContext *context = [self managedObjectContext];
	
	//istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza
	NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
	
	//istanziamo l'Entità da passare alla Fetch Request
	NSEntityDescription *entity = [NSEntityDescription 
								   entityForName:@"Contatto" inManagedObjectContext:context];
	//Settiamo la proprietà Entity della Fetch Request
	[fetchRequest setEntity:entity];
	
	//Eseguiamo la Fetch Request e salviamo il risultato in un array, per visualizzarlo nella tabella
	NSError *error;
	NSArray *fo = [context executeFetchRequest:fetchRequest error:&error];
	contattiList = [fo retain];
	
	[fetchRequest release];
	
	[contattiTable reloadData];
}

e nel metodo cellForRowAtIndexPath della tableview:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	static NSString *CellIdentifier = @"Cell";
	
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle 
									   reuseIdentifier:CellIdentifier] autorelease];
    }
	
    // Set up the cell...
	
	//istanziamo NSManagedObject perché gli oggetti dentro l'array sono di quel tipo
	NSManagedObject *contatto = [contattiList objectAtIndex:indexPath.row];
	
	//accediamo ai dati contenuti dal'oggetto utilizzando il Key-Value Coding
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", [contatto valueForKey:@"nome"], [contatto valueForKey:@"cognome"]];
    cell.detailTextLabel.text = [contatto valueForKey:@"nick"];

    return cell;
	
}

12. Impostiamo il comportamento della tastiera – parte seconda

Al momento la tastiera scompare solo quando schiacciamo Done e non quando premiamo Aggiungi Contatto. Per ovviare a questo inconveniente dobbiamo fare un check in addContatto su quale UITextField abbia il focus e farglielo rilasciare.
Aggiungiamo in cima al metodo addContatto in questo codice:

if ([nameField isFirstResponder]) {
			[nameField resignFirstResponder];
		} else if ([surnameField isFirstResponder]) {
			[surnameField resignFirstResponder];
		} else if ([nickField isFirstResponder]){
			[nickField resignFirstResponder];
		}

Un’altro inconveniente è che siamo liberi di aggiungere allo store di Core Data contatti con campi vuoti. A questo ovvieremo aggiungendo un if che controlli se uno o più dei nostri UITextField è vuoto, e in tal caso mostri un alert e non aggiunga il record.

A questo punto modifichiamo il nostro metodo addContatto in modo che il risultato finale sia questo:

- (IBAction) addContatto {
	//apriamo alertView se i campi non sono riempiti
	if (nameField.text.length == 0 || surnameField.text.length == 0 || nickField.text.length == 0) {
		
		//Costruiamo l'alert che ci impedisce di inserire un record senza tutti i campi
		NSString *titolo = @"Problema";
		NSString *messaggio = @"Devi inserire utti i campi!";
		
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:titolo
														message:messaggio
													   delegate:self
											  cancelButtonTitle:@"OK, non lo farò più."
											  otherButtonTitles:nil];
		
;
; } else { //per far sparire la tastiera if ([nameField isFirstResponder]) { [nameField resignFirstResponder]; } else if ([surnameField isFirstResponder]) { [surnameField resignFirstResponder]; } else if ([nickField isFirstResponder]){ [nickField resignFirstResponder]; } //Otteniamo il puntatore al NSManagedContext NSManagedObjectContext *context = [self managedObjectContext]; //Creiamo un'istanza di NSManagedObject per l'Entità che ci interessa NSManagedObject *contatto = [NSEntityDescription insertNewObjectForEntityForName:@"Contatto" inManagedObjectContext:context]; //Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'Entità appena creata [contatto setValue:surnameField.text forKey:@"cognome"]; [contatto setValue:nameField.text forKey:@"nome"]; [contatto setValue:nickField.text forKey:@"nick"]; //Effettuiamo il salvataggio gestendo eventuali errori NSError *error; if (![context save:&error]) { NSLog(@"Errore durante il salvataggio: %@", [error localizedDescription]); } //per pulire i campi NSString *clear = [NSString stringWithFormat:@""]; [nameField setText:clear]; [surnameField setText:clear]; [nickField setText:clear]; } }

13. Abbiamo finito

Ecco, il nostro programma d’esempio è pronto, testatelo aggiungendo e mostrando contatti.
Il codice di questo esempio è scaricabile dal mio github.

Riassunto

Abbiamo fatto la conoscenza delle classi usate in Core Data, costruito un’entità, inserito e caricato dati.

Nella prossima puntata

  • Useremo il wizard di Xcode per generare le classi del Model, in modo da poter accedere alle proprietà direttamente e non tramite il Key Value Coding.
  • Aggiungeremo la possibilità di modificare i record
  • Parleremo delle differenze fra il paradigma di Core Data e quello dei database relazionali
Share this story:
  • tweet

Tags: core dataNSEntityDescriptionNSFetchRequestNSManagedObjectNSManagedObjectContextNSManagedObjectModelNSPersistentStoreCoordinatorNSPredicateSQLiteTutorial PraticiXML iPhone

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • Android e SQLite: comandi precompilati con SqliteStatement

    18 Dicembre 2017 - 0 Comment
  • Android app con database interno: guida passo passo

    27 Novembre 2017 - 2 Comments
  • Android e database: operazioni rapide con la classe DatabaseUtils

    21 Novembre 2017 - 0 Comment

Author Description

14 Responses to “T#081 – Guida all’uso di Core Data (Parte 1)”

  1. 7 Dicembre 2010

    skip

    ottimo articolo! impaziente di leggere la seconda parte! grandi

  2. 7 Dicembre 2010

    Francesco

    Ottimo proprio quello che cercavo, aspetto la seconda parte ;).

  3. 8 Dicembre 2010

    Carlo

    Chiaro e completo. Ben fatto!

  4. 10 Dicembre 2010

    Jack Uchiha

    Ottimo tutorial! Una sola domanda: una volta buttato giù lo schema dei dati, come si fa a popolare da codice la tabella?

  5. 11 Dicembre 2010

    doppioslash

    Questo è l’argomento di una delle prossime puntate 🙂
    Cmq, l’inserimento dei dati in Core Data resta quello che vediamo in addContatto.
    Cambia la fonte: non più l’interfaccia, ma qualcosa tipo un file CVS, o simili, di cui andrà effettuato il parsing.

  6. 13 Dicembre 2010

    Domi

    Ciao Claudia, grazie x il tutorial, molto interessante 🙂

    A quando la 2 parte? ce la regali prima di natale? 😀

  7. 21 Dicembre 2010

    SoleLuna

    Ottimo tutorial, non riesco però a farlo funzionare ne su un app view-based ne su utility app.
    Su window-based, come da tutorial, tutto ok.

    Qualche consiglio?

  8. 21 Dicembre 2010

    doppioslash

    @Domi sarà fatto 🙂
    @SoleLuna nel template view-based non c’è l’opzione per usare Core Data, quindi dovresti inserirlo tu. Tratterò come inserire Core Data in un progetto già esistente in un prossimo tutorial.
    In utility-based immagino che il problema sia che vorrai accedere a Core Data dai viewcontroller invece che dall’app delegate, come nel tutorial.
    E’ necessario passare il riferimento al NSManagedContext a ogni viewcontroller da cui vuoi accedere a Core Data, alcuni usano l’approccio a singleton, ma sembra che in genere se ne pentano.
    Io avevo progettato di trattare la questione insieme a NSFetchedResultsController, più avanti.

  9. 30 Dicembre 2010

    SoleLuna

    @doppioslash
    Ciao, scusa mi era sfuggita la tua risposta, allora sulla view-based non essendoci il codice core data l’avevo copiato dalla utility-based passando anche il riferimento al NSManagedContext ma proprio su questo passaggio l’app crashava.
    Allora son partita da una window based e mi son costruita tutte le view passando ad ognuna di esse NSManagedContex. Tutto funziona correttamente. Ora sto facendo dei test sulla seconda lezione, avrei una curiosità ma forse è meglio che scriva di la 🙂
    grazie

  10. 24 Marzo 2011

    Paolo

    Ciao, se posso permettermi una critica: l’dea di mettere tutto nell’App Delegate è una scelta un po’ infelice dal punto di vista didattica nei confronti di chi sa poco di programmazione Cocoa e sta imparando. Per fortuna in rete ho trovato, dopo molta fatica, il modo per richiamare dal view controller i metodi del core data presenti nell’app delegate, cosa affatto banale e che qui non viene spiegata: http://www.techotopia.com/index.php/An_iPhone_OS_Core_Data_Tutorial

  11. 26 Aprile 2011

    Michele

    Ciao doppioslash, volevo sapere come si fa a caricare una view a partire, per esempio, dell’id del contatto?

    Immaginiamo di creare un campo univoco “id”
    Quindi quando estraiamo i dati abbiamo a disposizione l’id.
    Vorrei che a click sulla riga della table, l’applicazione carichi un’altra view che estrae dal database tutte le informazioni del contatto a partire dall’id univoco.
    La domanda é: come faccio a passare l’id alla seconda view?

    Se vuoi puoi contattarmi a michele.giarratana@gmail.com

    Grazie

  12. 22 Maggio 2011

    Francesco_96


    Paolo:

    Ciao, se posso permettermi una critica: l’dea di mettere tutto nell’App Delegate è una scelta un po’ infelice dal punto di vista didattica nei confronti di chi sa poco di programmazione Cocoa e sta imparando. Per fortuna in rete ho trovato, dopo molta fatica, il modo per richiamare dal view controller i metodi del core data presenti nell’app delegate, cosa affatto banale e che qui non viene spiegata: http://www.techotopia.com/index.php/An_iPhone_OS_Core_Data_Tutorial

    Concordo pienamente, inoltre il nuovo articolo promesso non sembra arrivare…

  13. 3 Agosto 2012

    Nicolas

    Ciao io ho gia un progetto avviato e non ho spuntato l’ opzione coredata a suo tempo non e’ che puoi fare a breve un tutorial? Grazie.


    doppioslash:

    @Domi sarà fatto
    @SoleLuna nel template view-based non c’è l’opzione per usare Core Data, quindi dovresti inserirlo tu. Tratterò come inserire Core Data in un progetto già esistente in un prossimo tutorial.
    In utility-based immagino che il problema sia che vorrai accedere a Core Data dai viewcontroller invece che dall’app delegate, come nel tutorial.
    E’ necessario passare il riferimento al NSManagedContext a ogni viewcontroller da cui vuoi accedere a Core Data, alcuni usano l’approccio a singleton, ma sembra che in genere se ne pentano.
    Io avevo progettato di trattare la questione insieme a NSFetchedResultsController, più avanti.

  14. 22 Agosto 2012

    Andrea

    Ciao,
    come mai quando modifico gli attributi di una entità e poi provo a lanciare l’applicazione mi ritorna l’errore:
    “The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store.”?

    Grazie!

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO