iOSCiao,

oggi vorrei parlarti della possibilità di accrescere i dati all’interno di un’applicazione iOS adoperando i servizi presenti su un server e come protocollo per il flusso dati il formato JSON.

Qualche anno fa, con l’arrivo degli smartphone ad uso massivo, l’uso dei servizi web ha avuto un incremento notevole. I protocolli adoperati erano, però, studiati per sistemi dotati di potenza e scopi differenti.

Fondamentalmente si delinearono due tipi di flussi usati in maggioranza, quello adoperante il protocollo XML generico e quello adoperante la sua specializzazione, il protocollo SOAP. Essendo flussi nati per contenere non solo il dato ma anche la tipologia dello stesso (o quantomeno una sua descrizione) la quantità di dati trasmessa tra il server ed il client risultava ben maggiore del dato stesso.

Inoltre, essendo entrambi i protocolli basati su stringhe, una volta giunto il flusso al dispositivo mobile, l’elaborazione degli stessi risultava particolarmente onerosa. Attualmente questi flussi dati sono comunque molto usati nell’ambito dello scambio di informazioni attraverso i servizi, nel frattempo è emerso però un nuovo tipo di flusso denominato JSON (Javascript Object Notation). Punto di forza di questo protocollo è la sua semplicità (anche se il dato non è in grado di autodescriversi) e l’estrema semplicità nell’essere trattato tramite il linguaggio Javascript, infatti il suo principale uso è proprio nello scambio dati secondo il protocollo AJAX.

Vista la semplicità intrinseca del formato e la quantità minore di dati necessaria a far transitare il flusso di informazioni, il formato JSON è divenuto popolare anche nell’ambito mobile. Inizialmente lo scambio dati ha richiesto l’uso di componenti di terze parti come ad esempio la libreria JSONKit che ancora oggi mantiene un primato di velocità di elaborazione del flusso dati invidiabile. Visto il successo di tale protocollo la stessa Apple ha deciso di adottarlo per lo scambio dei dati a partire dalla versione 5 di iOS scegliendo, come spesso accade, un approccio semplice, elegante e potente tramite l’uso della classe NSJSONSerialization  disponibile direttamente nel Foundation Framework.

Il compito di questa classe è serializzare e/o deserializzare un flusso JSON. In pratica fornendo un flusso dati, o tramite un oggeto NSData o tramite uno stream di tipo NSInputStream) esso si occuperà di convertire tale oggetto in classi valide per il linguaggio Objective-C in modo automatico permettendo di trattarne direttamente il contenuto.

Ma come è possibile adoperare questa classe?

Come primo passo è necessario identificare un flusso da elaborare, un esempio tipico di flusso JSON è il seguente:

{
	"amici" :
	[
		{ "id": "1", "nome" : "Andrea", "cellulare" : "+393334567890" },
		{ "id": "2", "nome" : "Francesca", "cellulare" : "+393474567890" },
		{ "id": "3", "nome" : "Simona", "cellulare" : "+393934567890" }
	]
}

Il flusso precedente potrebbe rappresentare una rubrica di amici in cui ognuno è identificato da un id e di ognuno possiamo avere il nome ed il numero di telefono.

Vediamo come ottenere il flusso dal server (il cui indirizzo è: http://localhost:8080/amici.php).:

NSURL *urlServerJSON = [NSURL URLWithString:@"http://localhost:8080/amici.php"];
NSData* datiJSON = [NSData dataWithContentsOfURL:urlServerJSON];

Nel nostro oggetto NSData è contenuto, quindi, il flusso grezzo da elaborare. E’ importante sapere come la classe NSJSONSerialization  trasformerà i dati. La prima cosa da sapere è che l’oggetto radice restituito dopo la trasformazione può essere di due tipi: NSArray o NSDictionary, l’oggetto restituito dipende da come il flusso JSON originario è strutturato.

La struttura di un flusso JSON è basata sulla coppia Chiave/Valore, ovvero che ogni elmento è identificato da una chiave alla quale è associato un valore. Quest’ultimo può essere un tipo scalare semplice come un intero, un numero in virgola mobile o una stringa (anche se quest’ultima non fa parte dei tipi scalari semplici) o, a sua volta può essere un ulteriore raggruppamento di valori identificati dalla struttura Chiave/Valore (convertita un NSDictionary) o da un elenco di tali raggruppamenti (convertito in un NSArray), essendo un tipo di struttura ricorsiva e non potendo essere il primo elmento un tipo scalare semplice (visto che ogni elemento deve essere identificato dalla coppia chiave valore) ecco che l’elemento radice deve necessariamente essere un NSDictionary o un NSArray.

Nell’esempio di questo articolo il risultato sarà un NSDictionary con all’interno un sola coppia Chiave/Valore. Per quest’ultima la chiave sarà “amici” (le chiavi sono sempre intese come di tipo NSString) ed il valore sarà un NSArray composto da tre elementi di tipo NSDictionary.

Ecco il codice che si occupa di effettuare la conversione:

NSError* error;
NSDictionary* rubricaAmici = [NSJSONSerialization JSONObjectWithData:datiJSON options:kNilOptions error:&error];

Il primo parametro è l’istanza di NSData contenente il flusso grezzo. Il secondo parametro serve ad indicare il metodo di creazione dei singoli oggetti contenenti i dati del flusso. In questo caso si intende che gli oggetti saranno tutti di tipo non mutevole, quindi per poterli modificare andranno ricopiati a loro volta in nuovi oggetti. Questo fa si che l’integrità dei dati venga preservata; infine il terzo parametro contiene un riferimento ad un puntatore di tipo NSError che verrà valorizzato in caso la conversione fallisca. Se la conversione non riesce il risultato sarà nil.

Nel caso tu non sappia che tipo di dato ti verrà restituito dopo la conversione puoi adattare il codice seguente per trattarlo:

NSError *jsonError = nil; 
id jsonObject = [NSJSONSerialization JSONObjectWithData:datiJSON options:kNilOptions error:&jsonError]; 
if (jsonObject) {
	if ([jsonObject isKindOfClass:[NSArray class]]) { 
		// Stiamo trattando un array
		NSArray *jsonArray = (NSArray *)jsonObject; 
		// Elaboro quindi le informazioni
	} 
	else { 
		// Stiamo trattando un dictionary
		NSDictionary *jsonDictionary = (NSDictionary *)jsonObject; 
		// Elaboro quindi le informazioni
	} 
}

Infine alcune considerazioni sul perchè scegliere la classe inclusa nell’SDK al posto di librerie di terze parti. La prima è più immediata è la semplicità, come hai visto il codice da scrivere è veramente poco e soprattutto è molto efficace in quanto ti permette di convertire il flusso in poche righe. La seconda considerazione è legata all’uso di ARC. Quest’ultimo è infatti l’approccio consigliato da Apple per la gestione della memoria. Purtroppo librerire come JSONKit non sono strutturate per essere adoperate agevolmente con ARC lasciando il loro stato indefinito al momento dell’uso (anche attivando lo switch per disabilitare la compilazione con ARC). Quindi queste ultime vanno adoperate solo nei casi in cui ARC non è adoperato o quando le performance hanno la precedenza su tutto.

Appuntamento al prossimo suggerimento,

Roberto S.



Related Posts Plugin for WordPress, Blogger...

Tagged with:  
Wordpress Code Snippet by Allan Collins