{"id":5246,"date":"2010-12-06T12:44:18","date_gmt":"2010-12-06T11:44:18","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=5246"},"modified":"2010-12-06T12:45:06","modified_gmt":"2010-12-06T11:45:06","slug":"t081-guida-alluso-di-core-data-parte-1","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t081-guida-alluso-di-core-data-parte-1\/","title":{"rendered":"T#081 &#8211; Guida all&#8217;uso di Core Data (Parte 1)"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t081-usare-core-data-iphone-ipad-00.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t081-usare-core-data-iphone-ipad-00.png\" alt=\"t081-usare-core-data-iphone-ipad-00\" title=\"t081-usare-core-data-iphone-ipad-00\" width=\"191\" height=\"146\" class=\"alignleft size-full wp-image-5302\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t081-usare-core-data-iphone-ipad-00.png 382w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t081-usare-core-data-iphone-ipad-00-300x229.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/t081-usare-core-data-iphone-ipad-00-150x114.png 150w\" sizes=\"auto, (max-width: 191px) 100vw, 191px\" \/><\/a> Ciao, sono Claudia e in questo mio primo articolo su devapp.it vi parler\u00f2 di Core Data.<\/p>\n<h4>1. Cos&#8217;\u00e8 e cosa non \u00e8 Core Data<\/h4>\n<p>L&#8217;esatta definizione della natura di Core Data \u00e8 di solito l&#8217;oggetto di complesse perifrasi, viene di volta in volta frainteso e considerato un ORM o un database.<br \/>\nLa 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.<br \/>\nIn pratica Core Data \u00e8 per il Model ci\u00f2 che Interface Builder \u00e8 per il View, non si occupa solo della persistenza, ma anche di gestire i dati in memoria, del passaggio da una versione all&#8217;altra e dell&#8217;undo.<br \/>\nSia iTunes che apple.com sono ospitati su un server Web Objects, tecnologia da cui si \u00e8 evoluto il design di Core Data.<!--more--><\/p>\n<h4>2. Considerazioni pratiche<\/h4>\n<p>Core Data \u00e8 in grado di salvare i dati in tre diversi formati: file binario, file xml e database SQLite. Per le app iOS \u00e8 di gran lunga preferibile SQLite in quanto meno avido di risorse.<br \/>\nFornisce anche meccanismi per gestire gli inevitabili cambiamenti di formato nella vita dell&#8217;app.<br \/>\nE&#8217; possibile aggiungere Core Data ad un&#8217;app gi\u00e0 esistente, ne parleremo in un prossimo tutorial.<\/p>\n<h4>3. In questo tutorial<\/h4>\n<p>Costruiremo una piccola applicazione che inserisce e carica dati.<br \/>\nLe classi che utilizzeremo sono:<\/p>\n<ul>\n<li><em>NSManagedObjectModel<\/em>: \u00e8 la classe che contiene la descrizione dei dati, Entit\u00e0 in Core Data, che vengono salvati nel database. Per questo useremo lo strumento grafico presente in Xcode.<\/li>\n<li><em>NSManagedObjectContext<\/em>: \u00e8 lo stesso concetto del context di Core Graphics: \u00e8 come una lavagna. I cambiamenti fatti in un contesto possono essere salvati o annullati. E&#8217; la classe che frequenteremo di pi\u00f9, perch\u00e9 ogni volta che si vogliono ottenere, inserire o cancellare dati chiameremo i suoi metodi.<\/li>\n<li><em>NSPersistentStoreCoordinator<\/em>: dove si setta la path del database utilizzato dall&#8217;app, chiamato dal contesto quando registra i cambiamenti.<\/li>\n<li><em>NSFetchRequest<\/em>: la usiamo quando vogliamo fare ricerche nei dati. Funziona in modo simile ai comandi SQL, definiamo quale Entit\u00e0 vogliamo ottenere ed eventuali parametri di filtraggio.<\/li>\n<li><em>NSEntityDescription<\/em>: la usiamo per definire l&#8217;Entit\u00e0 per la Fetch Request.<\/li>\n<li><em>NSPredicate<\/em>: la usiamo per definire i criteri di filtraggio per la Fetch Request.<\/li>\n<li><em>NSManagedObject<\/em>: ogni istanza di questa classe rappresenta un&#8217;Entit\u00e0. Accediamo alle sue propriet\u00e0 utilizzando il <strong>Key-Value Coding<\/strong>. Se vogliamo accedere alle propriet\u00e0 direttamente \u00e8 necessario subclassare <strong>NSManagedObject<\/strong>, ne parleremo in un prossimo tutorial.<\/li>\n<\/ul>\n<h4>4. Cominciamo!<\/h4>\n<p>Creiamo un nuovo progetto Window-based e accertiamoci che l&#8217;opzione <em>Use Core Data for Storage<\/em> sia selezionata.<br \/>\nLo chiameremo <strong>CoreDataPart1<\/strong>. Per non perdere tempo con codice estraneo a Core Data inseriremo l&#8217;interfaccia direttamente nell&#8217;App Delegate (non fatelo a casa!).<br \/>\nApriamo MainWindow.xib e inseriamo l&#8217;interfaccia come nella figura.<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/interfaccia-xib.png\" alt=\"L'interfaccia costruita in IB\" \/><br \/>\n<\/center><\/p>\n<h4>5. Sistemiamo gli outlet<\/h4>\n<p>Inseriamo nell&#8217;App Delegate gli <em>IBOutlet<\/em> e le <em>IBAction<\/em> per interagire con l&#8217;interfaccia, colleghiamoli in IB e non dimentichiamo di aggiungere <em>UITableViewDataSource<\/em> alla lista dei protocolli supportati dalla classe e di collegare in IB i delegati della tableView all&#8217;AppDelegate.<\/p>\n<p>Apriamo il file <strong>CoreDataPart1AppDelegate.h<\/strong> e aggiungiamo queste variabili d&#8217;istanza:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nIBOutlet UITextField *nameField;\r\nIBOutlet UITextField *surnameField;\r\nIBOutlet UITextField *nickField;\r\nIBOutlet UITableView *contattiTable;\r\n<\/pre>\n<p>Aggiungiamo i metodi legati ai nostri due pulsanti:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (IBAction) showContatti;\r\n- (IBAction) addContatto;\r\n<\/pre>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-Outlet1.png\" alt=\"Gli outlet da collegare in MainWindow.xib\" \/><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-Outlet2.png\" alt=\"I delegati da collegare per la TableView in MainWindow.xib\" \/><br \/>\n<\/center><\/p>\n<h4>6. Impostiamo il comportamento della tastiera &#8211; parte prima<\/h4>\n<p>Per fare in modo che la tastiera sparisca una volta completato l&#8217;inserimento, cos\u00ec da non nascondere la nostra interfaccia, dobbiamo manipolare le impostazioni degli UITextField in IB, settare come delegato l&#8217;AppDelegate, inserire <em>UITextFieldDelegate<\/em> fra la lista dei protocolli supportati nell&#8217;AppDelegate ed inserire il metodo <em>textFieldShouldReturn:<\/em> nel nostro file di implementazione:<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-TextFieldDelegate.png\" alt=\"Collegare il delegato di ogni TextField all'AppDelegate\" \/><br \/>\n<\/center><\/p>\n<p>In IB settiamo le propriet\u00e0 della tastiera per ogni UITextField, per primi due sceglieremo <strong>Next<\/strong> come <strong>Return Key<\/strong>, per l&#8217;ultimo <strong>Done<\/strong>:<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-KeyBoard1.png\" alt=\"Impostazione delle propriet\u00e0 della tastiera, primi due TextField\" \/><br \/>\n<\/center><\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-KeyBoard2.png\" alt=\"Impostazione delle propriet\u00e0 della tastiera, ultimo TextField\" \/><br \/>\n<\/center><\/p>\n<p>Apriamo il file <strong>CoreDataPart1AppDelegate.m<\/strong> e aggiungiamo questo metodo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (BOOL)textFieldShouldReturn:(UITextField *)textField {\r\n\t\/\/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\r\n\tif (textField == nameField) {\r\n\t\t[surnameField becomeFirstResponder];\r\n\t}\r\n\telse if (textField == surnameField) {\r\n\t\t[nickField becomeFirstResponder];\r\n\t}\r\n\r\n\t[textField resignFirstResponder]; \r\n\treturn YES;\r\n}\r\n<\/pre>\n<h4>7. Inseriamo i metodi di UITableViewDataSource<\/h4>\n<p>Aggiungiamo anche il codice necessario a gestire la tabella: aggiungiamo un <em>NSArray<\/em> alle variabili d&#8217;istanza e i metodi del protocollo <em>UITableViewDataSource<\/em>:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nNSArray *contattiList;\r\n<\/pre>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {\r\n\treturn 1;\r\n}\r\n\r\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {\r\n\treturn [contattiList count];\r\n}\r\n\r\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\r\n\tstatic NSString *CellIdentifier = @\"Cell\";\r\n\t\r\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\r\n    if (cell == nil) {\r\n        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle \r\n\t\t\t\t\t\t\t\t\t   reuseIdentifier:CellIdentifier] autorelease];\r\n    }\r\n    \/\/ Set up the cell...\r\n    return cell;\r\n\t\r\n}\r\n<\/pre>\n<h4>8. E&#8217; il momento di Core Data!<\/h4>\n<p>Diamo un&#8217;occhiata al codice che il template inserisce automaticamente per noi; nell&#8217;App Delegate vediamo tre nuove variabili d&#8217;istanza, corrispondenti alle classi presentate prima, <em>managedObjectContext<\/em>, <em>managedObjectModel<\/em> e <em>persistentStoreCoordinator<\/em>. Nei loro accessori troviamo cose interessanti, come la path del database utilizzato dall&#8217;app in <em>persistentStoreCoordinator<\/em>, una volta localizzato possiamo aprirlo con qualunque utility SQLite e notarne la struttura insolita.<br \/>\nInserire dati esterni in un database SQLite creato da Core Data sar\u00e0 l&#8217;oggetto di un prossimo tutorial.<\/p>\n<p>Procediamo nell&#8217;esplorazione del progetto, la nostra prossima tappa \u00e8 il file <strong>.xcdatamodel<\/strong>, dove potremo definire graficamente il nostro Model.<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-xcdataeditor-empty.png\" alt=\"L'editor di xcdatamodel\" \/><br \/>\n<\/center><\/p>\n<h4>9. Definiamo l&#8217;Entit\u00e0<\/h4>\n<p>Inseriamo il nostro oggetto nel box <strong>Entity<\/strong>, cliccando sul tasto +, modifichiamo il suo nome nel pannello all&#8217;estrema destra, chiamiamolo Contatto, la sua classe \u00e8 <em>NSManagedObject<\/em> non \u00e8 una classe astratta e non ha genitore.<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-datiEntity.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-datiEntity-300x222.png\" alt=\"\" title=\"CD-datiEntity\" width=\"300\" height=\"222\" class=\"alignnone size-medium wp-image-5267\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-datiEntity-300x222.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-datiEntity-150x111.png 150w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-datiEntity.png 307w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<h4>10. E le propriet\u00e0<\/h4>\n<p>Nel box Property aggiungiamo 3 propriet\u00e0, utilizzando anche qui il tasto + e scegliendo <strong>Add Attribute<\/strong>. Cognome, Nome e Nick, sono tutte di tipo stringa  non sono opzionali.<\/p>\n<p><center><br \/>\n<img decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2010\/12\/CD-AddAttribute.png\" alt=\"Aggiungere una propriet\u00e0 con l'editor di xcdatamodel\" \/><br \/>\n<\/center><\/p>\n<h4>11. E il codice dei metodi che usano Core Data<\/h4>\n<p>Ecco definita la nostra classe <strong>Model<\/strong>. Adesso andiamo ad aggiungere nel metodo <strong>addContatto<\/strong> il codice necessario per <strong>inserire l&#8217;oggetto nello store di Core Data<\/strong>.<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (IBAction) addContatto {\r\n\t\/\/Otteniamo il puntatore al NSManagedContext\r\n\tNSManagedObjectContext *context = [self managedObjectContext];\r\n\t\r\n\t\/\/Creiamo un'istanza di NSManagedObject per l'Entit\u00e0 che ci interessa\r\n\tNSManagedObject *contatto = [NSEntityDescription\r\n\t\t\t\t\t\t\t\t\t   insertNewObjectForEntityForName:@\"Contatto\" \r\n\t\t\t\t\t\t\t\t\t   inManagedObjectContext:context];\r\n\t\r\n\t\/\/Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'Entit\u00e0 appena creata\r\n\t[contatto setValue:surnameField.text forKey:@\"cognome\"];\r\n\t[contatto setValue:nameField.text forKey:@\"nome\"];\r\n\t[contatto setValue:nickField.text forKey:@\"nick\"];\r\n\t\r\n\t\/\/Effettuiamo il salvataggio gestendo eventuali errori\r\n\tNSError *error;\r\n\tif (![context save:&error]) {\r\n\t\tNSLog(@\"Errore durante il salvataggio: %@\", [error localizedDescription]);\r\n\t}\r\n}\r\n<\/pre>\n<p>Per visualizzare i dati andiamo ad aggiungere questo codice a <strong>showContatti<\/strong>:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (IBAction) showContatti {\r\n\t\/\/Otteniamo il puntatore al NSManagedContext\r\n\tNSManagedObjectContext *context = [self managedObjectContext];\r\n\t\r\n\t\/\/istanziamo la classe NSFetchRequest di cui abbiamo parlato in precedenza\r\n\tNSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];\r\n\t\r\n\t\/\/istanziamo l'Entit\u00e0 da passare alla Fetch Request\r\n\tNSEntityDescription *entity = [NSEntityDescription \r\n\t\t\t\t\t\t\t\t   entityForName:@\"Contatto\" inManagedObjectContext:context];\r\n\t\/\/Settiamo la propriet\u00e0 Entity della Fetch Request\r\n\t[fetchRequest setEntity:entity];\r\n\t\r\n\t\/\/Eseguiamo la Fetch Request e salviamo il risultato in un array, per visualizzarlo nella tabella\r\n\tNSError *error;\r\n\tNSArray *fo = [context executeFetchRequest:fetchRequest error:&error];\r\n\tcontattiList = [fo retain];\r\n\t\r\n\t[fetchRequest release];\r\n\t\r\n\t[contattiTable reloadData];\r\n}\r\n<\/pre>\n<p>e nel metodo <strong>cellForRowAtIndexPath<\/strong> della tableview:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {\r\n\tstatic NSString *CellIdentifier = @\"Cell\";\r\n\t\r\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\r\n    if (cell == nil) {\r\n        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle \r\n\t\t\t\t\t\t\t\t\t   reuseIdentifier:CellIdentifier] autorelease];\r\n    }\r\n\t\r\n    \/\/ Set up the cell...\r\n\t\r\n\t\/\/istanziamo NSManagedObject perch\u00e9 gli oggetti dentro l'array sono di quel tipo\r\n\tNSManagedObject *contatto = [contattiList objectAtIndex:indexPath.row];\r\n\t\r\n\t\/\/accediamo ai dati contenuti dal'oggetto utilizzando il Key-Value Coding\r\n    cell.textLabel.text = [NSString stringWithFormat:@\"%@ %@\", [contatto valueForKey:@\"nome\"], [contatto valueForKey:@\"cognome\"]];\r\n    cell.detailTextLabel.text = [contatto valueForKey:@\"nick\"];\r\n\r\n    return cell;\r\n\t\r\n}\r\n<\/pre>\n<h4>12. Impostiamo il comportamento della tastiera &#8211; parte seconda<\/h4>\n<p>Al momento la tastiera scompare solo quando schiacciamo <strong>Done<\/strong> e non quando premiamo <strong>Aggiungi Contatto<\/strong>. Per ovviare a questo inconveniente dobbiamo fare un check in <strong>addContatto<\/strong> su quale UITextField abbia il focus e farglielo rilasciare.<br \/>\nAggiungiamo in cima al metodo <strong>addContatto<\/strong> in questo codice:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nif ([nameField isFirstResponder]) {\r\n\t\t\t[nameField resignFirstResponder];\r\n\t\t} else if ([surnameField isFirstResponder]) {\r\n\t\t\t[surnameField resignFirstResponder];\r\n\t\t} else if ([nickField isFirstResponder]){\r\n\t\t\t[nickField resignFirstResponder];\r\n\t\t}\r\n<\/pre>\n<p>Un&#8217;altro inconveniente \u00e8 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\u00f9 dei nostri UITextField \u00e8 vuoto, e in tal caso mostri un alert e non aggiunga il record.<\/p>\n<p>A questo punto modifichiamo il nostro metodo <strong>addContatto<\/strong> in modo che il risultato finale sia questo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (IBAction) addContatto {\r\n\t\/\/apriamo alertView se i campi non sono riempiti\r\n\tif (nameField.text.length == 0 || surnameField.text.length == 0 || nickField.text.length == 0) {\r\n\t\t\r\n\t\t\/\/Costruiamo l'alert che ci impedisce di inserire un record senza tutti i campi\r\n\t\tNSString *titolo = @\"Problema\";\r\n\t\tNSString *messaggio = @\"Devi inserire utti i campi!\";\r\n\t\t\r\n\t\tUIAlertView *alert = [[UIAlertView alloc] initWithTitle:titolo\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tmessage:messaggio\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   delegate:self\r\n\t\t\t\t\t\t\t\t\t\t\t  cancelButtonTitle:@\"OK, non lo far\u00f2 pi\u00f9.\"\r\n\t\t\t\t\t\t\t\t\t\t\t  otherButtonTitles:nil];\r\n\t\t<div class=\"alert\"><button type=\"button\" class=\"close\">&#215;<\/button><div class=\"clear\"><\/div><\/div>;\r\n\t\t<div class=\"alert\"><button type=\"button\" class=\"close\">&#215;<\/button><div class=\"clear\"><\/div><\/div>;\r\n\t\t\r\n\t} else {\r\n\t\t\/\/per far sparire la tastiera\r\n\t\tif ([nameField isFirstResponder]) {\r\n\t\t\t[nameField resignFirstResponder];\r\n\t\t} else if ([surnameField isFirstResponder]) {\r\n\t\t\t[surnameField resignFirstResponder];\r\n\t\t} else if ([nickField isFirstResponder]){\r\n\t\t\t[nickField resignFirstResponder];\r\n\t\t}\r\n\t\t\r\n\t\t\/\/Otteniamo il puntatore al NSManagedContext\r\n\t\tNSManagedObjectContext *context = [self managedObjectContext];\r\n\t\t\r\n\t\t\/\/Creiamo un'istanza di NSManagedObject per l'Entit\u00e0 che ci interessa\r\n\t\tNSManagedObject *contatto = [NSEntityDescription\r\n\t\t\t\t\t\t\t\t\t insertNewObjectForEntityForName:@\"Contatto\" \r\n\t\t\t\t\t\t\t\t\t inManagedObjectContext:context];\r\n\t\t\r\n\t\t\/\/Usando il Key-Value Coding inseriamo i dati presi dall'interfaccia nell'istanza dell'Entit\u00e0 appena creata\r\n\t\t[contatto setValue:surnameField.text forKey:@\"cognome\"];\r\n\t\t[contatto setValue:nameField.text forKey:@\"nome\"];\r\n\t\t[contatto setValue:nickField.text forKey:@\"nick\"];\r\n\t\t\r\n\t\t\/\/Effettuiamo il salvataggio gestendo eventuali errori\r\n\t\tNSError *error;\r\n\t\tif (![context save:&error]) {\r\n\t\t\tNSLog(@\"Errore durante il salvataggio: %@\", [error localizedDescription]);\r\n\t\t}\r\n\t\t\r\n\t\t\/\/per pulire i campi\r\n\t\tNSString *clear = [NSString stringWithFormat:@\"\"];\r\n\t\t\r\n\t\t[nameField setText:clear];\r\n\t\t[surnameField setText:clear];\r\n\t\t[nickField setText:clear];\r\n\t}\r\n\r\n}\r\n<\/pre>\n<h4>13. Abbiamo finito<\/h4>\n<p>Ecco, il nostro programma d&#8217;esempio \u00e8 pronto, testatelo aggiungendo e mostrando contatti.<br \/>\nIl codice di questo esempio \u00e8 scaricabile dal mio <a href=\"http:\/\/www.github.com\/doppioslash\/DevappTutorials\">github<\/a>.<\/p>\n<h4>Riassunto<\/h4>\n<p>Abbiamo fatto la conoscenza delle classi usate in Core Data, costruito un&#8217;entit\u00e0, inserito e caricato dati.<\/p>\n<h4>Nella prossima puntata<\/h4>\n<ul>\n<li>Useremo il wizard di Xcode per generare le classi del Model, in modo da poter accedere alle propriet\u00e0 direttamente e non tramite il Key Value Coding.<\/li>\n<li>Aggiungeremo la possibilit\u00e0 di modificare i record<\/li>\n<li>Parleremo delle differenze fra il paradigma di Core Data e quello dei database relazionali<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Ciao, sono Claudia e in questo mio primo articolo su devapp.it vi parler\u00f2 di Core Data. 1&#8230;.<\/p>\n","protected":false},"author":343,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[502,507,506,509,504,503,505,508,102,224],"class_list":["post-5246","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-core-data","tag-nsentitydescription","tag-nsfetchrequest","tag-nsmanagedobject","tag-nsmanagedobjectcontext","tag-nsmanagedobjectmodel","tag-nspersistentstorecoordinator","tag-nspredicate","tag-sqlite","tag-xml-iphone"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5246","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/343"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=5246"}],"version-history":[{"count":46,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5246\/revisions"}],"predecessor-version":[{"id":5306,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/5246\/revisions\/5306"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=5246"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=5246"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=5246"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}