{"id":8411,"date":"2012-01-19T12:28:15","date_gmt":"2012-01-19T11:28:15","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=8411"},"modified":"2012-01-19T12:28:15","modified_gmt":"2012-01-19T11:28:15","slug":"t106-json-e-ios-5-creiamo-il-client-iphone-per-il-nostro-web-service-php-parte-2","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/t106-json-e-ios-5-creiamo-il-client-iphone-per-il-nostro-web-service-php-parte-2\/","title":{"rendered":"T#106 \u2013 JSON e iOS 5: creiamo il client iPhone per il nostro web service PHP (Parte 2)"},"content":{"rendered":"<p><a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/json.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/json.jpg\" alt=\"json JavaScript Object Notation\" title=\"json JavaScript Object Notation\" width=\"192\" height=\"119\" class=\"alignleft size-full wp-image-8420\" \/><\/a> Come promesso nel <a href=\"http:\/\/www.devapp.it\/wordpress\/t105-json-e-ios-5-creiamo-il-backend-con-json-e-php-parte-1.html\" target=\"_blank\">precedente tutorial<\/a>, creeremo oggi un client iOS utilizzando le grandi novit\u00e0 di iOS5, utilizzeremo infatti sia ARC che Storyboard.<br \/>\nIniziamo creando un nuovo progetto di tipo &#8220;Empty application&#8221;. Potremmo selezionare anche &#8220;Master-detail Application&#8221;, ma ci troveremmo troppa pappa pronta e questo non va bene.<!--more--><\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_06.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_06-300x207.png\" alt=\"\" width=\"300\" height=\"207\" class=\"aligncenter size-medium wp-image-8305\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_06-300x207.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_06-1024x709.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_06.png 1120w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Chiamiamo il progetto JSClient e assicuriamoci di aver selezionato &#8220;iPhone&#8221; e &#8220;Use automatic reference counting&#8221; come mostrato in foto:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_07.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_07-300x207.png\" alt=\"\" width=\"300\" height=\"207\" class=\"aligncenter size-medium wp-image-8307\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_07-300x207.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_07-1024x709.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_07.png 1120w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>L&#8217;applicazione in questo momento \u00e8 veramente vuota per cui bisogna aggiungere almeno un file storyboard, aggiungiamolo cliccando su file-&gt;new file e selezionando la voce &#8220;storyboard&#8221;:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_08.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_08-300x207.png\" alt=\"\" width=\"300\" height=\"207\" class=\"aligncenter size-medium wp-image-8308\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_08-300x207.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_08-1024x709.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_08.png 1120w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Attenzione a selezionare iPhone come Device Family.<\/p>\n<p>Dobbiamo ora fare in modo che l&#8217;app utilizzi questo file per caricare l&#8217;interfaccia e per far ci\u00f2 selezioniamo l&#8217;icona del progetto in alto a sinistra e scegliamo il corretto storyboard dalla combobox Main Storyboard:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_09.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_09-300x214.png\" alt=\"\" width=\"300\" height=\"214\" class=\"aligncenter size-medium wp-image-8309\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_09-300x214.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_09-1024x730.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_09.png 1349w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>C&#8217;\u00e8 un&#8217;altra modifica da effettuare affich\u00e9 venga correttamente utilizzato lo storyboard e consiste nell&#8217;eliminare il contenuto del metodo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions\r\n<\/pre>\n<p>Nell&#8217;appdelegate, assicuratevi semplicemente di mantenere un:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\nreturn TRUE;\r\n<\/pre>\n<p>Possiamo passare alla creazione dell&#8217;interfaccia dentro lo storyboard. Se non l&#8217;avete mai utilizzato potete farvi un&#8217;idea leggendo l&#8217;articolo <a href=\"http:\/\/www.devapp.it\/wordpress\/t103-introduzione-all-uso-di-storyboard.html\" target=\"_blank\">Introduzione a Storyboard<\/a>.<\/p>\n<p>Trasciniamo sullo storyboard un UITableViewController e scegliamo &#8220;embed in-&gt; navigation controller&#8221; dal men\u00f9 Editor, otterremo questo risultato:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_102.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_102-300x207.png\" alt=\"\" width=\"300\" height=\"207\" class=\"aligncenter size-medium wp-image-8313\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_102-300x207.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_102-1024x708.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_102.png 1248w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Come abbiamo gi\u00e0 detto nel precedente articolo, abbiamo trascinato un <em>generico<\/em> tableViewController, ma a noi serve una nostra classe che erediti da tableViewController, aggiungiamo quindi un nuovo file al progetto (sempre file-&gt;new file) selezionando la voce UIViewController Subclass e scegliendo infine UITableViewController dalla combobox SubClass of:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_11.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_11-300x203.png\" alt=\"\" width=\"300\" height=\"203\" class=\"aligncenter size-medium wp-image-8315\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_11-300x203.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_11.png 727w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>.<br \/>\n<\/center><\/p>\n<p>A questo punto possiamo specificare all&#8217;interno del file storyboard che il tableviewcontroller non \u00e8 un generico tableviewcontroller, ma una istanza dell&#8217;appena inserito MainTableViewController.<\/p>\n<p>Selezioniamolo quindi all&#8217;interno del file storyboard e settiamone correttamente la propriet\u00e0 custom class come mostrato nello screenshot:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_12.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_12-279x300.png\" alt=\"\" width=\"279\" height=\"300\" class=\"aligncenter size-medium wp-image-8317\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_12-279x300.png 279w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_12.png 674w\" sizes=\"auto, (max-width: 279px) 100vw, 279px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Vogliamo che selezionando un contatto dalla tabella venga visualizzata una view con i dettagli di quel contatto. Per questo ci servir\u00e0 un secondo viewController. Trasciniamo quindi nello storyboard un viewController standard e trasciniamo dalla cella del tableViewController verso il viewController appena creato e selezioniamo &#8220;push&#8221; dal men\u00f9 che viene visualizzato. Questo sar\u00e0 il risultato:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_13.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_13-300x150.png\" alt=\"\" width=\"300\" height=\"150\" class=\"aligncenter size-medium wp-image-8323\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_13-300x150.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_13-1024x512.png 1024w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_13.png 1332w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>Anche in questo caso abbiamo usato un generico viewController, ma in realt\u00e0 ci servir\u00e0 uno specifico viewController, aggiungiamolo quindi da file-&gt;new file e poi modifichiamo lo storyboard affinch\u00e9 rispecchi la nuova classe, allo stesso modo di come abbiamo fatto poco fa con il MainTableViewController.<\/p>\n<p>Ci serviranno 4 textField per visualizzare i dettagli del contatto selezionato e per fare ci\u00f2 sfruttiamo una comoda funzionalit\u00e0 del nuovo XCode, apriamo lo storiboard e trasciniamo 4 textfield sul viewcontroller, selezioniamo la visualizzazione dell&#8217;assistant editor e trasciniamo dalle textfield verso l&#8217;intestazione della classe:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_14.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_14-300x258.png\" alt=\"\" width=\"300\" height=\"258\" class=\"aligncenter size-medium wp-image-8325\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_14-300x258.png 300w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_14.png 896w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>In questo modo verranno automaticamente create le quattro property necessarie per accedere alle textfield.<\/p>\n<h4>Realizzazione della logica applicativa<\/h4>\n<p>Possiamo passare ora a realizzare la parte di logica del programma che ci permetter\u00e0 di scaricare il JSON dal nostro server e visualizzare i contatti nella tabella.<\/p>\n<p>Apriamo il file MainTableViewController e aggiungiamo un&#8217;array come variabile di istanza dove memorizzare tutti i contatti:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@property (nonatomic, strong) NSArray *contatti;\r\n<\/pre>\n<p>non dimentichiamoci:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@synthesize contatti;\r\n<\/pre>\n<p>nel file MainTableViewController.m.<\/p>\n<p>All&#8217;interno del metodo viewDidLoad occupiamoci di interrogare il server per ottenere il JSON, ma non lo faremo nel thread principale, useremo invece il gran central dispatcher per eseguire il download in background. Modifichiamo quindi il metodo in questo modo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)viewDidLoad\r\n{\r\n    [super viewDidLoad];\r\n    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{\r\n        NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@\"http:\/\/localhost:8888\"]];\r\n        [self performSelectorOnMainThread:@selector(fetchedData:)\r\n                               withObject:data waitUntilDone:YES]; });\r\n}\r\n<\/pre>\n<p>Come potete notare dopo aver scaricato il JSON ed averlo memorizzato all&#8217;interno dell&#8217;oggetto data richiamiamo fetchedData, che si occuper\u00e0 di effettuare il parsing.<\/p>\n<p>Il metodo \u00e8 questo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)fetchedData:(NSData *)responseData {\r\n    NSArray* json = [NSJSONSerialization\r\n                          JSONObjectWithData:responseData \/\/1\r\n                          options:kNilOptions error:nil];    \r\n    self.contatti = json;\r\n    [self.tableView reloadData];\r\n}\r\n<\/pre>\n<p>Tutta la magia avviene grazie alla classe NSJSONSerialization ed al suo metodo <strong>JSONObjectWithData:options:error<\/strong> che si occupa di parsare il JSON e restituire un array di dizionari. Fin troppo semplice, non credete?<\/p>\n<p>Infatti ci tocca complicare un po&#8217; le cose ed adesso vediamo insieme il perch\u00e9.<\/p>\n<p>Con i due metodi precedenti abbiamo interrogato un webservice e ricevuto un JSON contenente una lista di contatti e, una volta ricevuta tale lista, abbiamo inserito in un array tanti oggetti NSDictionary quanti sono i contatti ricevuti. Ma l&#8217;oggetto NSDictionary \u00e8 un tipo generico non \u00e8 una nostra classe il che porta (magari non in questo esempio, ma di sicuro nella vita reale) ad avere diversi problemi durante la stesura del progetto. Vediamo quali sono i pregi derivanti dall&#8217;utilizzo di una classe:<\/p>\n<ul>\n<li>le variabili di istanza hanno dei nomi fissi che possiamo controllare nell&#8217;header della classe<\/li>\n<li>le variabili di istanza possono essere incapsulate dai metodi get e set<\/li>\n<li>Il nostro codice sarebbe pi\u00f9 facile da leggere perch\u00e9 un oggetto di tipo Contatto \u00e8 pi\u00f9 identificabile di un generico NSDictionary<\/li>\n<li>Possiamo aggiungere metodi specifici che non sono previsti in un NSDictionary<\/li>\n<li>&#8230;la lista potrebbe continuare&#8230;<\/li>\n<\/ul>\n<p>Sperando di avervi convinto creiamo subito la classe &#8220;Contatto&#8221; (file-&gt;new file-&gt;NSObject subclass) che ha semplicemente 4 propriet\u00e0 di tipo NSString, non credo ci sia bisogno di particolari istruzioni, qui c&#8217;\u00e8 il codice completo:<\/p>\n<p>Questo \u00e8 il file Contatto.h<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import \r\n\r\n@interface Contatto : NSObject\r\n@property (strong, nonatomic) NSString *nome;\r\n@property (strong, nonatomic) NSString *cognome;\r\n@property (strong, nonatomic) NSString *dataNascita;\r\n@property (strong, nonatomic) NSString *sesso;\r\n@end\r\n<\/pre>\n<p>e questo \u00e8 il file Contatto.m<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n#import \"Contatto.h\"\r\n\r\n@implementation Contatto\r\n@synthesize nome,cognome,dataNascita,sesso;\r\n@end\r\n<\/pre>\n<p>Creata la nostra classe possiamo aggiungere un #import Contatto in cima al file MainTableViewController.h e modificare il metodo fetchedData: in questo modo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)fetchedData:(NSData *)responseData {\r\n    NSArray* json = [NSJSONSerialization\r\n                          JSONObjectWithData:responseData \/\/1\r\n                          options:kNilOptions error:nil];\r\n    NSMutableArray *contattiTMP = [[NSMutableArray alloc] initWithCapacity:[json count]]; \/\/2\r\n    for (NSDictionary *dict in json) { \/\/3\r\n        Contatto *c = [[Contatto alloc] init]; \/\/4\r\n        \r\n        c.nome          = [dict objectForKey:@\"nome\"];\r\n        c.cognome       = [dict objectForKey:@\"cognome\"];\r\n        c.dataNascita   = [dict objectForKey:@\"datanascita\"];\r\n        c.sesso         = [dict objectForKey:@\"sesso\"];\r\n        [contattiTMP addObject:c]; \/\/5\r\n    }\r\n    \/\/mi assicuro che l'array contatti non possa essere modificato.\r\n    self.contatti = [contattiTMP copy]; \/\/6\r\n    [self.tableView reloadData];\r\n}\r\n<\/pre>\n<ol>\n<li>Il parser dell&#8217;oggetto responseData \u00e8 rimasto uguale al precedente, quindi nessun cambiamento<\/li>\n<li>Dichiariamo e inizializziamo un NSMutablearray, ci servir\u00e0 per memorizzare le istanze della classe Contatti<\/li>\n<li>Eseguo un ciclo for su tutti gli oggetti dell&#8217;array restituito dal parser JSON<\/li>\n<li>Per ogni iterazione creo un nuovo oggetto di tipo Contatto e ne imposto le propriet\u00e0 leggendole dal dizionario.<\/li>\n<li>Infine aggiungo il Contatto all&#8217;array<\/li>\n<li>Terminata la procedura di creazione dei contatti assegno alla variabile di istanza contatti una copia dell&#8217;NSMutableArray creato al punto 2, questo perch\u00e9 ho scelto che tale variabile sia immutabile e quindi non voglio assegnargli un NSMutableArray.<\/li>\n<\/ol>\n<p>Passiamo ora ai metodi relativi alla tabella:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView\r\n{\r\n    return 1;\r\n}\r\n\r\n- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section\r\n{\r\n    return [contatti count];\r\n}\r\n\r\n- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath\r\n{\r\n    static NSString *CellIdentifier = @\"Cell\";\r\n    \r\n    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];\r\n    if (cell == nil) {\r\n        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];\r\n    }\r\n    cell.textLabel.text = [[contatti objectAtIndex:indexPath.row] nome];\r\n    \/\/ Configure the cell...\r\n    \r\n    return cell;\r\n}\r\n<\/pre>\n<p>e lanciamo l&#8217;applicazione. Il risultato sar\u00e0 questo:<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/Screen-Shot-2012-01-08-at-11.10.16-PM.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/Screen-Shot-2012-01-08-at-11.10.16-PM-159x300.png\" alt=\"\" width=\"159\" height=\"300\" class=\"aligncenter size-medium wp-image-8327\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/Screen-Shot-2012-01-08-at-11.10.16-PM-159x300.png 159w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/Screen-Shot-2012-01-08-at-11.10.16-PM.png 396w\" sizes=\"auto, (max-width: 159px) 100vw, 159px\" \/><\/a><br \/>\n<\/center><\/p>\n<p>La gestione della tabella \u00e8 gi\u00e0 stata trattata in molti altri articoli, ed in questo caso non presenta nessuna particolarit\u00e0, se avete dei dubbi non esitate a chiedere.<\/p>\n<p>Passiamo alla visualizzazione del dettaglio. Vogliamo fare in modo che cliccando su una cella &#8220;Mario&#8221; vengano visualizzati i dati dell&#8217;utente &#8220;Mario&#8221;. Se avete seguito correttamente la parte di questo articolo relativa alla costruzione dello storyboard dovreste gi\u00e0 poter cliccare sulla cella e vedere il viewcontroller di dettaglio, che per\u00f2 \u00e8 vuoto. Vuoto perch\u00e9 nessuno gli ha detto che dati visualizzare!<\/p>\n<p>Il metodo che dobbiamo implementare per avere il controllo del viewcontroller di dettaglio \u00e8 questo:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{    \r\n    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender]; \/\/1\r\n    Contatto *c = [self.contatti objectAtIndex:indexPath.row]; \/\/2\r\n    DetailViewController *dvc = (DetailViewController *)[segue destinationViewController]; \/\/3\r\n}\r\n<\/pre>\n<ol>\n<li>Otteniamo l&#8217;indexpath della cella che \u00e8 stata selezionata<\/li>\n<li>Recuperiamo l&#8217;oggetto Contatto dall&#8217;array usando l&#8217;indexPath<\/li>\n<li>Recuperiamo l&#8217;istanza del viewcontroller di dettaglio  usando il metodo destinationViewController<\/li>\n<\/ol>\n<p>A questo punto abbiamo il riferimento al viewControlle di dettaglio ed un approccio &#8220;poco lungimirante&#8221; (eufemismo) potrebbe essere quello di impostare direttamente il valore delle textField con i valori prelevati dall&#8217;oggetto Contatto&#8230; Questo non \u00e8 un buon approccio perch\u00e9 nell&#8217;ottica di separare quanto \u00e8 possibile logiche e responsabilit\u00e0 dobbiamo prevedere la possibilit\u00e0 che DetailViewController venga modificato, per esempio, usando una webView piuttosto che quattro textField, se usassimo l&#8217;approccio &#8220;poco lungimirante&#8221; ciascuna modifica, anche minima, alla classe DetailViewController dovrebbe propagarsi anche alla classe MainTableViewController e di sicuro non \u00e8 quello che vogliamo (in inglese di parla di &#8220;coupling&#8221; e &#8220;de-coupling&#8221; spero di aver dato l&#8217;idea del loro significato).<\/p>\n<p>In questo caso quindi che facciamo? Basta ragionare un&#8217;attimo sullo scopo principale per il quale abbiamo creato la classe DetailViewController, che \u00e8 quello di visualizzare i dettagli di uno specifico Contatto. <\/p>\n<p>Allora di cosa ha bisogno per poter assolvere al suo compito? Beh, a bisogno che qualcuno gli dica quale contatto visualizzare, no?<\/p>\n<p>Quindi modifichiamo il metodo precedente aggiungendo proprio il passaggio dell&#8217;oggetto Contatto:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{    \r\n    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];\r\n    Contatto *c = [self.contatti objectAtIndex:indexPath.row];\r\n    DetailViewController *dvc = (DetailViewController *)[segue destinationViewController];\r\n    [dvc setContatto:c]; \/\/4\r\n}\r\n<\/pre>\n<p>Al punto 4 vi dar\u00e0 errore perch\u00e9 ancora la classe DetailViewController non ha alcun metodo setContatto. Lo aggiungeremo adesso.<\/p>\n<p>Selezioniamo il file DetailViewController.h aggiungiamo #import &#8220;Contatto.h&#8221; in cima al file e una property di tipo Contatto:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n@property (strong, nonatomic) Contatto *contatto;\r\n<\/pre>\n<p>Nel file DetailViewController.m non dimentichiamoci di aggiungere @syntetize contatto.<\/p>\n<p>Possiamo ora modificare il metodo viewdidLoad in modo da visualizzare correttamente i dettagli del contatto:<\/p>\n<pre lang=\"objc\" line=\"1\" escaped=\"true\">\r\n- (void)viewDidLoad\r\n{\r\n    self.nome.text          = contatto.nome;\r\n    self.cognome.text       = contatto.cognome;\r\n    self.datanascita.text   = contatto.dataNascita;\r\n    self.sesso.text         = contatto.sesso;\r\n    [super viewDidLoad];\r\n}\r\n<\/pre>\n<p>Ammiriamo finalmente il nostro programma in tutto il suo splendore! \ud83d\ude42<\/p>\n<p><center><br \/>\n<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_15.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_15-279x300.png\" alt=\"\" width=\"279\" height=\"300\" class=\"aligncenter size-medium wp-image-8398\" srcset=\"https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_15-279x300.png 279w, https:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2012\/01\/TUT_JSON_15.png 480w\" sizes=\"auto, (max-width: 279px) 100vw, 279px\" \/><\/a><br \/>\n<\/center><\/p>\n<h4>E adesso?<\/h4>\n<p>Se avete seguito per intero questo lungo tutorial avrete notato che abbiamo messo veramente tanta carne al fuoco, quindi sta a voi capire che cosa approfondire.<br \/>\nSe vi interessa la parte web potreste trovare utile approfondire il php (<a href=\"http:\/\/www.w3schools.com\/php\/\" title=\"Corso php w3c\" target=\"_blank\">Corso php w3c<\/a>) o perch\u00e9 no uno dei tanti framework per lo sviluppo in questo linguaggio come <a href=\"http:\/\/www.symfony-project.org\/\" target=\"_blank\">simfony<\/a>  o <a href=\"http:\/\/codeigniter.com\/\" target=\"_blank\">codeigniter<\/a>.<br \/>\nQuesti framework utilizzano un&#8217;approccio diverso al database rispetto all&#8217;esempio qui proposto, ma un buon programmatore non pu\u00f2 esimersi dal conoscere almeno un p\u00f2 il linguaggio SQL (<a href=\"http:\/\/www.w3schools.com\/sql\/default.asp\" target=\"_blank\">Corso SQL w3c<\/a>).<\/p>\n<p>Se invece siete pi\u00f9 interessati alla parte iOS date un&#8217;occhiata a questo articolo (<a href=\"http:\/\/bonto.ch\/blog\/2011\/12\/06\/json-libraries-for-ios-comparison\/\" target=\"_blank\">JSON Benchmark<\/a>) in cui viene eseguito un benchmark sui vari framework per effettuare il parsing di un JSON, purtroppo scopriremo che il metodo usato qui non \u00e8 il pi\u00f9 veloce in assoluto (anche se si guadagna un onorevole secondo posto).<\/p>\n<p>Non mi resta che darvi il link del progetto completo, lo trovate su github a questo indirizzo: <a href=\"https:\/\/github.com\/ignazioc\/JSClient\" target=\"_blank\">JSClient<\/a> ed augurare a tutti buona programmazione!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Come promesso nel precedente tutorial, creeremo oggi un client iOS utilizzando le grandi novit\u00e0 di iOS5, utilizzeremo&#8230;<\/p>\n","protected":false},"author":53,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[1023,1025,1028,1027,1022,1026,982,1024],"class_list":["post-8411","post","type-post","status-publish","format-standard","hentry","category-tutorial-pratici","tag-arc-ios-5","tag-json-e-applicazioni-iphone","tag-json-e-iphone","tag-jsonobjectwithdataoptionserror","tag-nsjsonserialization","tag-parsing-json-xcode","tag-storyboard-xcode","tag-webservice-e-iphone"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8411","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\/53"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=8411"}],"version-history":[{"count":9,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8411\/revisions"}],"predecessor-version":[{"id":8431,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/8411\/revisions\/8431"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=8411"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=8411"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=8411"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}