Introduzione
Io ho la necessità per lavoro di crearmi una serie di applicazioni per Mac
e iOS che possano interagire tra di loro e salvare i dati in un database centralizzato
in modo che ci possa poi accedere anche via web attraverso un sito Internet.
Ho girato molto in Internet e non ho trovato frameworks soddisfacenti
per l’accesso diretto a database esterni a cocoa.
Parlando con gli ingegneri Apple, mi hanno suggerito di sfruttare
Internet e per la precisione Apache + PHP + MySQL.
Rimasto frastornato da questa risposta ho chiesto altre delucidazioni e mi
hanno detto di vedermi la sezione di networking del WWDC 2010 e 2011.
Dopo la visione mi si sono aperti gli occhi e ho iniziato a capire come funziona il tutto.
Ci sono ancora cosa che devo provare e chiarire, ma tempo al tempo!
Ed ecco la domanda… Ma come posso realizzare il tutto e fare comodamente delle prove?
Come primo step bisogna avere un server web funzionante a portata di mano.
Si può scegliere di acquistare un dominio e dello spazio Internet presso un qualsiasi ISP
tipo Aruba o kermat.net (sono io!!!), si può scegliere di ammattire per far funzionare
Apache già incluso con Lion oppure ci possiamo affidare ad
un software molto semplice che è MAMP. MAMP è l’acronimo
di Mac Apache Mysql Php, il programma viene distribuito
in due versioni: versione free e a pagamento.
Il tutorial si divide in varie fasi in modo da far capire bene i vari step
e sono organizzati in maniera progressiva:
- Installazione e configurazione MAMP su Lion;
- Realizzazione di una pagina di test in PHP;
- Realizzazione della pagina “botta e risposta” in PHP che chiameremo dall’applicazione;
- Realizzazione della prima applicazione;
- Realizzazione della seconda pagina in PHP che salverà i dati dentro MySQL;
- Realizzazione della seconda applicazione che salverà e richiamerà dei dati da MySQL.
Dopo questa lunga introduzione possiamo iniziare la prima fase del tutorial.
Naturalmente per poter procedere occorre avere la connessione Internet attiva e sapere
installare un programma su ambiente Mac e in particolare su Lion.
Prima di procedere mi sono creato la cartella “ApplicazioneWeb” all’interno dei mie Documenti.
Inizieremo questo lungo viaggio scaricando MAMP dal sito internet
http://www.mamp.info scegliendo la versione free.
Questa versione ci permette di poter creare e controllare un singolo dominio e
la versione a pagamento fino a 15 domini in contemporanea.
Terminato il download dell’applicativo si esegue l’installer facendo
il classico doppio click sul file MAMP.pkg che si trova nella directory download.
Il programma di installazione non richiede scelte particolari da fare quindi bast
a il solito avanti avanti avanti accetto accetto accetto…
Qui potrei inserire degli screeshot per mostrare le fasi
dal download alla conclusione dell’installazione.
Internet
Apache + PHP
MySQL
Ed ecco la domanda… Ma come posso realizzare il tutto e fare comodamente delle prove?
Come primo step bisogna avere un server web funzionante a portata di mano.
Si può scegliere di acquistare un dominio e dello spazio Internet presso un qualsiasi
ISP tipo Aruba o kermat.net (sono io!!!), si può scegliere di ammattire per far funzionare
Apache già incluso con Lion oppure ci possiamo affidare ad un software
molto semplice che è MAMP. MAMP è l’acronimo di Mac Apache Mysql Php,
il programma viene distribuito in due versioni: versione free e a pagamento.
Il tutorial si divide in varie fasi in modo da far capire bene i vari step e
sono organizzati in maniera progressiva:
- Installazione e configurazione MAMP su Lion;
- Realizzazione di una pagina di test in PHP;
- Realizzazione della pagina “botta e risposta” in PHP che chiameremo dall’applicazione;
- Realizzazione della prima applicazione;
- Realizzazione della seconda pagina in PHP che salverà i dati dentro MySQL;
- Realizzazione della seconda applicazione che salverà e richiamerà dei dati da MySQL.
Dopo questa lunga introduzione possiamo iniziare la prima fase del tutorial.
Naturalmente per poter procedere occorre avere la connessione Internet attiva
e sapere installare un programma su ambiente Mac e in particolare su Lion.
Ora che MAMP funziona egregiamente non ci rimane che fare un test di collaudo
scrivendo una piccola pagina in PHP.
Per fare ciò io uso DreamViewer, ma può essere usato qualsiasi programma anche gratuito come Editra.
L’importante è che il nome del file rimanga invariato a come lo scrivo su questa guida.
Prima di passare a scrivere codice su Xcode creiamo la pagina PHP che ci serve richiamare.
Io voglio che nella mia applicazione ci sia un campo di testo dove metterò
il mio nome e cognome (o del testo qualunque) e una label dove i
l programma mi scriverà la risposta di Apache.
Apro il mio editor PHP preferito e scrivo:
<?php
if( is_array( $_REQUEST ) && isset( $_REQUEST[‘testo’] ) )
{
if( $_REQUEST[‘testo’] != “” )
{
echo “Ciao ” . $_REQUEST[‘testo’];
} else
echo “1001”;
} else
echo “1002”;
?>
Salvo la pagina come il nome di prova.php dentro la directory
ApplicazioneWeb che si trova sempre dentro Documenti.
Il codice controlla che venga passata una url del tipo http://localhost/prova.php?testo=
e in caso contrario restituisce la stringa “1002” che mi servirà sulla
mia applicazione a mostrare il corretto messaggio di errore.
Il codice controlla che ci sia del testo dopo http://localhost/prova.php?testo=
e se non è presente mi restituisce il valore di errore “1001”.
Questi numeri li ho scelti io. E’ quindi possibile cambiarli basta
ricordarsi di fare altrettanto sull’applicazione.
Se tutto è nella norma, ovvero la pagina è stata chiamata con
i parametri giusti e del testo in aggiunta, php resistuirà alla nostra
applicazione la stringa “Ciao, ” più il testo inserito nella nostra applicazione.
Simuliamo il tutto da safari:
Ora non ci rimane che scrivere la nostra applicazione per provare
il passaggio dei datida Xcode verso Apache e poi da Apache verso Xcode.
1 – Apro Xcode e sceglo “Create a new Xcode project di tipo Cocoa Application
2- Ho deciso di chiamare questa applicazione “TestApache”
3 – Faccio click sul file xib e inizio a creare l’interfaccia grafica
4- L’interfaccia grafica conclusa. Ha due label, un TextField e un PushButton
5 – Inizio a creare la nuova classe: File -> New -> New File.->Objective-c class
Chiamo la classe “TestHTTP” e la dichiaro sottoclasse di “NSBobject”. Alla schermata successiva faccio click su “Create”.
Nel file TestHTTP.h vado a scrivere il seguente codice:
[code lang=”objc”]
#import <Foundation/Foundation.h>
@interface testHTTP : NSObject
{
IBOutlet NSTextField *delTesto;
IBOutlet NSTextField *laRisposta;
}
– (IBAction) testHTTPstart:(id)sender;
@end
[/code]
Ho dichiarato due IBOutlet: uno sarà legato al TextFiled (delTesto) e
l’altro sarà legato alla Label (laRisposta). Ho creato poi un
IBAction per il pulsante.
Nel file TestHTTP.m vado a scrivere il seguente codice ( commenterò una funzione alla volta…):
[code lang=”objc”]
#import "testHTTPclass.h"
NSURLConnection *theConnection;
NSMutableData *receivedData;
@implementation testHTTPclass
– (id)init
{
self = [super init];
if (self) {
// Initialization code here.
receivedData = [[NSMutableData alloc] init];
}
return self;
}
[/code]
Ho dichiarato due variabili di cui la prima terrà al suo interno la connessione
che stabilirò con Apache e la seconda conterrà il risultato fornito da Apache.
Ho allocato in memoria e poi inizializzato la variabile receivedData
dentro il costrutto in init. le variabili
theConnection e receivedData dichiarate a questo modo le posso usare da funzioni a funzioni ma solo sulla classe.
[code lang=”objc”]
– (IBAction)testHTTPstart:(id)sender
{
NSString *myUrl = [@"<a href="http://46.31.110.83/test.php?testo=">http://localhost/prova.php?testo=</a>" stringByAppendingString:[NSString stringWithFormat:@"%@", [delTesto stringValue]]];
myUrl =[myUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"delTesto: %@", myUrl);
[laRisposta setStringValue: myUrl];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:myUrl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
[/code]
Questa funzione è il cuore della mia classe. Ho inizializzato una stringa
NSString in maniera un po complessa. Nel dettaglio mi serviva creare la stringa per
la connessione ad Apache sommando la stringa “http://localhost/prova.php?testo=” con il contenuto
del TextField. L’intero comando inizializza la variabile myURL
con la stringa “http://localhost/prova.php?testo=” di defualt e a questa viene
aggiunta (stringByAppendingString) una seconda stringa (NSString stringWithFormat:@”%@”)
che risulta essere [delTesto stringValue].
Ho notato che se scrivevo “ciao mondo” nel campo testo poi si incasinava quando
creava la connessione per via dello spazio. Ho quindi usato del codice che mi cambia
il carattere spazio con la dicitura %20 per le url.
Scrivo nel log la variabile myURL per controllare che venga scritta in maniera corretta.
Inizializzo la mia connessione theRequest passandogli come url da chiamare quella che ho generato prima.
Setto un timeout vero il server di 60 secondi, scaduto il quale l’applicazione mi sputa
nella label che non riesce a connettersi al server.
Poi come ultima cosa avvio la mia connessione e imposto la ricezione dei dati da Apache.
[code lang=”objc”]
– (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
NSLog(@"Received chunk of size %zu", (size_t) [receivedData length] );
}
[/code]
Questa funzione non fa altro che ricevere tutti i segmenti della trasmissione
da parte di apache e aggiungerli di volta in volta alla variabile receivedData
dichiarata in precedenza. Nel log mostra l’andamento dell’operazione.
In questo modo si possono ricevere anche file di grandi dimensioni.
[code lang=”objc”]
– (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
{
NSLog(@"Succeeded! Received %lu bytes of data",[receivedData length]);
NSString *s = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSLog(@"Stringa: %@", s);
[laRisposta setStringValue: s];
[receivedData setData:NULL];
}
[/code]
Funzione che viene chiamata alla fine della ricezione dei dati da parte di Apache. Come prima cosa mando un messaggio di successo al log.
Dichiaro e inizializzo una stringa temporanea s con il contenuto di receivedData.
Ho dovuto anche ricodificare la stringa e trasformarla in codice ASCII standard.
Scrivo sul log quello che ho ricevuto da Apache.
Ora non ci rimane che mostrare cosa abbiamo ricevuto da Apache.
Imposto la Label (laRisposta) con il valore contenuto nella variabile dichiarata poco prima s.
Poi per terminare azzero la variabile receivedData. Questo è un passaggio
molto importante perchè altrimenti ogni volta che premo il pulsante mi si
accoderebbe quello che apache mi restituisce.
[code lang=”objc”]
– (void)connection:(NSURLConnection *)theConnection
didFailWithError:(NSError *)error
{
NSLog(@"Connection failed! Error – %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
[/code]
Ultima funzione che viene chiamata nel caso ci sia qualche errore con
la connessione e mi viene scritto tutto nel log.
Ecco ora l’intero codice senza le spiegazioni.
[code lang=”objc”]
#import "testHTTPclass.h"
NSURLConnection *theConnection;
NSMutableData *receivedData;
@implementation testHTTPclass
– (id)init
{
self = [super init];
if (self) {
receivedData = [[NSMutableData alloc] init];
}
return self;
}
– (IBAction)testHTTP:(id)sender
{
NSString *myUrl = [@"<a href="http://46.31.110.83/test.php?testo=">http://46.31.110.83/test.php?testo=</a>" stringByAppendingString:[NSString stringWithFormat:@"%@", [delTesto stringValue]]];
myUrl =[myUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"delTesto: %@", myUrl);
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:myUrl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
}
– (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
NSLog(@"Received chunk of size %zu", (size_t) [receivedData length] );
– (void)connectionDidFinishLoading:(NSURLConnection *)theConnection
{
NSLog(@"Succeeded! Received %lu bytes of data",[receivedData length]);
NSString *s = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSLog(@"Stringa: %@", s);
[laRisposta setStringValue: s];
[receivedData setData:NULL];
}
– (void)connection:(NSURLConnection *)theConnection
didFailWithError:(NSError *)error
{
NSLog(@"Connection failed! Error – %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
@end
}
[/code]
Occupiamoci ora delle connessioni così da vedere, finalmente, la nostra applicazione funzionare!!!
Rechiamoci nel file . xib e inseriamo 2 text field e un push botton
Aggiungo il famoso cubo blù “Object” e nell’ispector gli associo la classe “TestHTTP”
Ora faccio le solite mosse per creare le connessioni e in questo caso sono tre:
- Connessione tra la classe e il TextField;
- Connessione tra la classe e la Label;
- Connessione tra la classe e il pulsante.
Effettuate le connessioni si può provare il nostro programma
(avviare pirma MAP!!! Altrimenti non funziona!!!)
e se tutto è stato fatto nella maniera giusta otterremo quanto segue: