Eccoci con un nuovo tutorial dedicato alla programmazione per iPhone SDK. Oggi vedremo come implementare un database SQL con SQLite all’interno delle nostre applicazioni. Il database sarà molto semplice, creeremo infatti un’unica tabella che conterrà un elenco di nomi di persone. Questi record (ovvero i nomi salvati nel database) verranno mostrati successivamente in una TableView all’interno della nostra applicazione. Vedremo quindi anche come interrogare il nostro database con una semplicissima query.
Devo premettere, però, che non parlerò di SQL e database relazionali, i quali devono essere già conosciuti da chi affronta questo tutorial. È una scelta che potrebbe sicuramente non piacere a molti di voi, ciò nonostante capirete che una trattazione completa sull’argomento richiederebbe troppo tempo e non potrebbe essere certo proposta in un semplice tutorial pratico. Detto ciò, sappiate che potrete seguire il tutorial anche senza conoscere niente di SQL, ovviamente alcune caratteristiche e alcuni passaggi potrebbero risultare di difficile comprensione.
In questo tutorial sentirete spesso parlare di SQLite, ma cosa è di preciso?
SQLite è una libreria che implementa un DBMS (Database Management System) SQL, permettendo di creare un database all’interno di un unico file. Esso è molto indicato per scopi come il nostro, ovvero la creazione di semplici applicazioni per dispositivi mobili, che non possono permettersi di avere un DMBS dedicato per la gestione delle basi di dati. SQLite fornisce un supporto parziale all’SQL, in quanto manca di alcune caratteristiche avanzate, presenti invece in DBMS più evoluti. SQLite è comunque molto veloce e leggero, perfetto quindi per le applicazioni per iPhone.
Creiamo un nuovo progetto e la struttura necessaria
Iniziamo creando un nuovo progetto di tipo “Navigation-based Application” e chiamiamolo “sqlTutorial”

Abbiamo quindi creato un progetto che ci fornisce già l’implementazione di una tabella, che useremo per visualizzare i dati letti dal nostro database.
Dobbiamo, però, inserire altre due cose molto importanti:
- una classe che si occuperà di comunicare con il database
- la libreria che permette tale comunicazione
Iniziamo a creare la classe che servirà ai nostri scopi. Andiamo in “File -> New File…” e creiamo una nuova “Objective-C class”, chiamiamola semplicemente “Data”:

Dobbiamo ora inserire nel nostro progetto la libreria (o framework) che si occupa del collegamento con il database sql. Clicchiamo con il tasto destro sulla cartella “Frameworks” all’interno del nostro progetto, clicchiamo quindi su “Add -> Existing Frameworks…” e dall’elenco che apparirà selezioniamo “libsqlite3.0.dylib”:

Abbiamo così terminato la definizione della struttura principale del nostro progetto. Se avete eseguito tutto in maniera corretta dovreste avere un progetto simile a questo:

2) Definiamo la classe “Data”
Dobbiamo ora implementare la classe “Data”, su cui si basa gran parte di questo tutorial. Prima di iniziare a scrivere codice, focalizziamo l’attenzione su ciò che deve fare questa classe. Essa avrà il compito di:
- creare una connessione con il database (di cui noi specificheremo un indirizzo, in questo caso locale, ma nulla vieterebbe di avere un database in remoto);
- interrogare la base di dati eseguendo una query impostata via codice;
- inserire i risultati della query all’interno di un’array, che verrà poi utilizzato per mostrare i dati all’interno della tabella;
Vediamo ora di implementare queste funzionalità, più altre caratteristiche che ci serviranno come supporto.
Iniziamo aprendo il file “Data.h”. Apriamolo e inseriamo al suo interno il seguente codice:
#import
#import
@interface Data : NSObject {
// Lista contenente i dati letti dal database
NSMutableArray *lista;
}
- (id)init:(NSString *)pathDB;
- (void)caricaValoriDaDB:(NSString *)dbPath;
- (unsigned)getSize;
- (id)objectAtIndex:(unsigned)theIndex;
@property (nonatomic, retain) NSMutableArray *lista;
@end
Alla riga numero 6 abbiamo dichiarato un array (di tipo NSMutableArray, quindi modificabile anche dopo la sua inizializzazione), che conterrà i valori letti dal database. Dalla riga 9 alla 12 abbiamo invece definito i metodi che ci serviranno in questa classe, che implementeremo fra poco nel rispettivo file .m. Da notare, inoltre, la classe importata alla riga 2: è necessaria per dire alla nostra classe di utilizzare la libreria che abbiamo importato ad inizio della guida.
Apriamo ora il file “Data.m” e modifichiamo il suo codice come segue:
#import "Data.h"
static sqlite3 *database = nil;
@implementation Data
@synthesize lista;
// Inizializziamo l'oggetto della classe Data
- (id)init:(NSString *)pathDB{
// carichiamo i valori dal database
[self caricaValoriDaDB:pathDB];
return self;
}
// Ritorna la dimensione della lista (n° di elementi letti dal db)
- (unsigned)getSize {
return [lista count];
}
// Ritorna l'oggetto ad una data posizione
- (id)objectAtIndex:(unsigned)index {
return [lista objectAtIndex:index];
}
La prima istruzione degna di nota compare alla riga 3, ed è la definizione dell’oggetto che ci servirà per creare la connessione con il database.
Alla riga 10, invece, viene dichiarato il primo metodo, “init”, che deve essere invocato quando si vuole inizializzare un oggetto appartenente alla classe Data. Alla riga 12 chiamiamo il metodo “caricaValoriDaDB”, che ha il compito di interfacciarsi con il database ed eseguire le query sui dati (vedremo fra poco la sua implementazione). Il “return self” alla riga 13, infine, ritorna il puntatore dell’oggetto appena creato.
Alla riga 17 definiamo “getSize”, un semplice metodo che ci ritorna la dimensione della lista, e quindi il numero di elementi letti dalla nostra query. Questo ci servirà quando andremo a definire la tabella.
Infine, alla riga 22, definiamo un metodo che ci ritorna un oggetto presente ad una determinata posizione della nostra lista. Ad esempio, potremo recuperare il 5° elemento della nostra lista, per poi elaborarlo oppure mostrarlo all’utente.
Dobbiamo ora implementare il metodo più complesso di questa classe, ovvero “caricaValoriDaDB”. Ecco il codice di tale metodo:
// Carica i valori dal database passato come parametro
-(void)caricaValoriDaDB:(NSString *)dbPath {
// lista temporanea
NSMutableArray *listaTemp = [[NSMutableArray alloc] init];
// Oggetto che contiene i vari elementi
NSMutableDictionary *dictionary;
NSMutableString *idPersona;//id della persona
NSMutableString *nome;//nome della persona
NSMutableString *cognome;//cognome della persona
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
// query che ricava i valori
const char *sql = "select ID, Nome, Cognome from PERSONA";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
// ricaviamo i valori letti dalla query
idPersona = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
nome = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 1)];
cognome = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 2)];
// inseriamo tutti i valori letti in un unico oggetto
dictionary = [[NSMutableDictionary alloc] initWithObjectsAndKeys:idPersona, @"id", nome, @"nome", cognome, @"cognome", nil];
[listaTemp addObject:dictionary];
[dictionary release];
}
}
self.lista = listaTemp;
[listaTemp release];
}
else
sqlite3_close(database);
}
Iniziamo ad analizzare questo metodo. Partiamo dall’intestazione, in cui viene definito un parametro “dbPath”: questo è il percorso del nostro database. Esso lo definiremo in seguito, nella classe che gestisce la tabella. In questo tutorial il database sarà in locale, ovverò sarà fisicamente presente nella cartella del nostro progetto. Nulla vieta, comunque, di inserire un indirizzo, che ci consenta di connetterci ad un database presente su un server remoto.
Subito dopo, creiamo alcuni oggetti, che ci servono per gestire i dati ricavati dalle query. Abbiamo, infatti, un oggetto “dictionary”, che conterrà i vari elementi ricavati dall’interrogazione al database. Le stringhe “idPersona”, “nome”, “cognome”, infatti, servono per salvare i valori letti, e inserirli all’interno dell’oggetto appena menzionato.
Alla riga 37 viene aperta la connessione con il database: essa si trova all’interno di un ciclo “if”: se tale controllo da esito positivo, si possono elaborare i dati, altrimenti si passa alla fine del metodo, in quanto non è possibile instaurare una connessione con il database. Se la connessione è stata creata, possiamo creare la query che andremo poi ad eseguire (riga 39). Alla riga 42 eseguiamo poi tale query: anche in questo caso, se l’esecuzione ha avuto successo, possiamo ricavare i valori desiderati, altrimenti non verrà eseguita nessuna operazione.
Il ciclo while (riga 44) ci permetterà di scorrere tutti i risultati della nostra query (che potrebbero essere, ovviamente, più di uno), fino al termine. Potete notare che i risultati vengono inseriti in un oggetto di tipo “NSMutableDictionary”: esso è come un grande contenitore, che ci permette di inserire valori associandoci un tag (quello che facciamo alla riga 50).
Come vedete non si tratta di operazioni complesse, si tratta solo di capire come funziona il meccanismo, che potete poi variare a seconda delle vostre esigenze.
Gli ultimi due metodi da inserire nel file “Data.m” sono i seguenti:
+(void)finalizeStatements {
if(database)
sqlite3_close(database);
}
-(void)dealloc {
[lista release];
[super dealloc];
}
Il primo si occupa di concludere la query e di chiudere la connessione al database (va sempre messo), mentre il secondo è il classico “dealloc”.
Abbiamo concluso con la definizione della classe “Data”. Vediamo ora come creare il nostro database e inserirlo nel progetto.
3) Creiamo il database SQLite
Quello che dobbiamo andare a realizzare ora è un semplice database, con tecnologia SQLite. Possiamo lavorare da Terminale, per semplificarvi un po’ la vita, però, vi faremo vedere come crearlo utilizzando un plug-in per Firefox, chiamato “SQLite Manager“, che potete trovare a questo indirizzo. In alternativa esistono alcuni programmi dedicati, come SQLiteManager, che è, però, a pagamento.

Dopo aver installato l’estensione, andiamo in “Strumenti -> SQLite Manager”, si avvierà il tool che ci permetterà di creare il nostro database. Clicchiamo sull’icona del foglio bianco per crare un nuovo database:

e inseriamo “persone” come nome per il file:

Scegliamo ora dove salvare il file (vi consiglio sulla Scrivania, così potrete recuperarlo celermente in seguito).
Abbiamo così creato il nostro database, che risulta però essere completamente vuoto. Dobbiamo, quindi, creare al suo interno la tabella “Persone”. Per fare ciò, facciamo clic con il tasto destro su “Tables” che troviamo nella parte sinistra della schermata, e selezioniamo “Create Table”:

Si aprirà una nuova schermata, in cui dovremo definire gli attributi della tabella. Ecco cosa dobbiamo inserire:

Clicchiamo su “Ok” e su “Yes” nel messaggio successivo che apparirà.
Abbiamo inserito gli attributi necessari, ovvero nome, cognome e un identificativo univoco (id).
Non ci resta che inserire dei valori nella nostra tabella. Per fare ciò, andiamo nella sezione “Execute SQL” e inseriamo le seguenti istruzione:
INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('1','Giovanni','Verdi');
INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('2','Paolo','Rossi');
INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('3','Luca','Bianchi');
INSERT INTO PERSONA (id,Nome,Cognome) VALUES ('4','Andrea','Busi');

Un messaggio in “Last Error” ci comunicherà se vi sono stati errori nell’inserimento dei dati, oppure se tutto è andato per il verso giusto.
Possiamo, infine, controllare i valori che abbiamo inserito, spostandoci nella sezione “Browse & Search”:

Abbiamo concluso! Chiudiamo il programmino e firefox, i cambiamenti sono già stati apportati al nostro database.
4) Concludiamo l’applicazione
Torniamo ora ad XCode, e concludiamo lo sviluppo della nostra applicazione. Per prima cosa, dobbiamo inserire fisicamente il database che abbiamo creato all’interno del nostro progetto. Trasciniamo quindi il file all’interno di XCode:

Nella schermata che apparirà inseriamo la spunta su “Copy items into destination group’s folder” e clicchiamo su “Add”

Siamo pronti per completare la nostra applicazione. Apriamo il file “RootViewController.h” e inseriamo il seguente codice:
#import "Data.h"
@interface RootViewController : UITableViewController {
// Oggetto con la lista degli elementi letti dal db
Data *dataList;
}
@end
Alla riga 5 abbiamo dichiarato la lista che conterrà gli elementi letti dal database. Per capirci, è quella che viene creata dal metodo “caricaValoriDaDB”, che abbiamo definito in precedenza.
Passiamo ora al file “RootViewController.m”. Iniziamo con il metodo “viewDidLoad”, che, come ormai dovreste sapere, ci consente di eseguire delle operazioni al caricamento dell’applicazione. Ecco come dobbiamo modificare tale metodo:
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Lista Autori";
//leggiamo il path del database
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"persone.sqlite"];
//creiamo la lista degli autori
dataList = [[Data alloc] init:defaultDBPath];
}
Alla riga 4 impostiamo il titolo della nostra tabella, mentre alla riga 6 definiamo il percorso del nostro database. A prima vista può sembrare complessa, ma essa non fa altro che rilevare il percorso in cui si trova l’applicazione (sia essa su iPhone Simulator che su iPhone fisico) e aggiungere a tale percorso “persone.sqlite”, che è proprio il database che abbiamo inserito nel nostro progetto.
Alla riga 9, infine, inizializziamo la lista, passando alla funzione “init” proprio il percorso che abbiamo definito poche righe sopra.
Dobbiamo, ora, definire i metodi necessari per settare la tabella. Abbiamo già visto questi metodi nei tutorial dedicati alle tableView, quindi non mi soffermerò troppo sulla spiegazione. Sempre all’interno del file “RootViewController.m”, andiamo verso il fondo, e cerchiamo i metodi del protocollo UITableView, che dovremo completare nel seguente modo:
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [dataList getSize];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *itemAtIndex = (NSDictionary *)[dataList objectAtIndex:indexPath.row];
cell.textLabel.text = [itemAtIndex objectForKey:@"nome"];
return cell;
}
I tre metodi sono i soliti che vanno inseriti quando si lavora con le UITableView. Concentriamoci un attimo sulle righe 22 e 23. Esse hanno il compito di ricavare un oggetto dalla lista “dataLista” (che contiene tutti i valori letti dal database), per estrarne poi il nome desiderato (ovviamente vengono estratti tutti i nomi, dal primo all’ultimo). Potete vedere che dall’oggetto “itemAtIndex” viene estratto solo il nome: potremmo creare anche altre combinazioni, ad esempio con il cognome. Per fare ciò ci basterà modificare la riga 23 ad esempio nel seguente modo:
[itemAtIndex objectForKey:@"cognome"];
Abbiamo concluso la nostra applicazione! Clicchiamo su “Build and Go!” e controlliamo che funzioni tutto in maniera corretta.


79 Responses to “T#044 – Come implementare un database SQLite nelle nostre applicazioni”
29 Settembre 2011
Andrea BusiL’elemento dizionario che contiene il nome “Luca” contiene già l’ID, quindi quando l’utente seleziona una riga puoi fare questo per leggere nome e id:
29 Settembre 2011
Andrea BusiPuoi creare una nuova vista di dettaglio che abbia una property di tipo NSMutableDictionary. Quando l’utente seleziona una cella inizializzi questa nuova vista e gli passi l’oggetto in questione 😉
29 Settembre 2011
Alex…. in effetti! 😉 Grazie
29 Settembre 2011
Alexse la vista si chiama “vistadettaglio” e contiene il nuovodizionario come glielo passo l’oggetto dizionario dalla vista corrente?
30 Settembre 2011
AndreaCiao a tutti! Rivolgo la mia domanda specialmente ad Andrea Busi.
Nel commento #16 Rebe scrive:
“Rebe
Ciao di nuovo!
Ho risolto da sola il mio problema, lo scrivo qui, magari può servire a qualcuno!
La soluzione è stata fare una NSURLRequest da iPhone contenente un file php che implementa la query con la parola chiave passata in GET, seguita da una NSURLConnection della request.
Lo stesso file PHP crea dopo la query su DB un XML ad hoc con i risultati della medesima.
L’XML viene sequenzialmente alla NSURLRequest caricato sull’iPhone in una nuova View e parserizzato in modo da visualizzare sullo schermo i risultati.
Il tutorial sull’XML trovato qui sul sito è stato di grande aiuto per quest’ultima parte!
Grazie ancora, mi avete salvato un pezzo di tesi con le vostre dritte! :)”
E tu Andrea hai risposto:
“perfetto, meglio così!!
se per caso hai voglia di scriverci due righe, o anche solo un piccolo esempio su come hai fatto poi potremmo farne un articolo e renderlo disponibile per tutti 😉
facci sapere!”
—————————————————————————-
Ecco volevo chiederti se Rebe ti ha inviato qualche spezzone di codice o qualche esempio pratico. E’ la stessa identica cosa che sto cercando di implementare, ho capito il procedimento, però son alle prime armi e guardare qualche esempio mi sarebbe davvero utile! Ti ha inviato qualcosa Rebe? Potresti farmi avere qualcosa? Ho letto che avreste fatto un articolo, ma non ho trovato niente.
Grazie mille 🙂 🙂 🙂
30 Settembre 2011
Andrea BusiQuindi dopo averla allocata e istanziata potrai passargli il dizionario semplicemente:
la allochi
30 Settembre 2011
Andrea BusiCiao, purtroppo non ho mai avuto il materiale in questione da Rebe.
Ovviamente se qualcuno avesse del materiale ne saremmo molto felici, e provvederemmo subito a fare un tutorial qui su devAPP 😉
11 Ottobre 2011
SamueleMagari mi sbaglio, ma non conviene usare Core Data con sqlite?
13 Ottobre 2011
Andrea BusiSi, diciamo che CoreData è la soluzione più “elegante” e anche la più performante. Se uno non ha tempo di imparare CoreData, oppure ha necessità di utilizzare per forza SQL è obbligato invece a scegliere questa strada 😉
27 Ottobre 2011
StefanoGrazie per l’ottimo tutorial, ma avrei un dubbio…..se io avessi un database con più tabelle come potrei chiedere all’app di farmele visualizzare?
31 Ottobre 2011
Andrea BusiImposterai la query in modo che legga nelle tabelle necessarie. Se devi ricavare i dati da più tabelle che devono essere unite avrai bisogno di una JOIN tra le tabella 😉
31 Ottobre 2011
PlaceboQuindi conviene usare CoreData ?
Ho un project su device ipad e devo immagazzinare su db parecchi dati,
occupa meno risorse usare coreData che sqlite?
Esiste qualche esempio comparativo?
Grazie mille degli ottimi tutorial.
10 Novembre 2011
AngeloSalve, ma quindi una connessione diretta a un database remoto è possibile?
In questo forum avevo letto di no…
28 Novembre 2011
Andrea BusiNo, la connessione diretta a database remoti non è possibile, è necessario passare obbligatoriamente per un web service.
4 Febbraio 2012
fini87Ciao a tutti, scusate l’ignoranza, ma un programmatore, come vorrei diventare io, dovrebbe essere in grado di costruire tutte questo codice da solo, oppure cmq sempre si attinge da altri che già hanno pubblicato la sintassi??
Grazie a presto
4 Febbraio 2012
Andrea BusiCiao, dipende dal contesto. Ci sono classi e libreria già pronte (scritte da altri) che è inutile o troppo complesso riscrivere, quindi qualsiasi sviluppatore le utilizza così come sono.
Il codice che vedi in questo tutoral, però, ha una difficoltà media/semplice: richiede alcune conoscenze base di SQL, ma il codice in se non è nulla di complesso.
Se vuoi realizzare delle applicazioni, quindi, il codice di questo tutorial ti deve essere molto familiare 😉
20 Febbraio 2012
GianfrancoCiao e complimenti per il tutorial. Ho seguito con attenzione il tutorial e ho problemi quando devo implementare l’interfaccia UITableView. Con l’ultima versione di xcode non ci sono i file che crei nel progetto. Mi mancano solo gli ultimi metodi per finire l’esempio? Mi dai qualche dritta? Devo aggiungere un file? Se si quale?
29 Febbraio 2012
SundsCiao e grazie per il tutorial,
Tuttavia, se volessi visualizzare sia il nome che il cognome e il telefono, come implemento la vista?
grazie
14 Marzo 2012
M@Sunds: anche a me interessa
…e se avessi un db dinamico e
non statico come nel progetto qui sopra?
e esiste qui un tutorial dove viene spiegato
come fare se dovessi collegarmi ad un db Oracle
che varia i sui dati all’interno di giorno in giorno
e volessi visualizzarli su ipad?
thx
M
14 Marzo 2012
FabioMa non è stato dimenticato l’importantissimo sqlite3_finalize() ????
🙂 Prima di metterlo avevo dei leak paurosi! Il close non è sufficiente
Dopo ogni prepare va un finalize:
The application must finalize every [prepared statement] in order to avoid
** resource leaks.
23 Marzo 2012
MBDavvero un ottimo tutorial!
solo una cosa a me sul file Data.h all riga di codice [dictionary release]; mi da il seguente problema mi dice che ‘release’ is unavaible e poi ARC forbids explicit message send of ‘release’.
Qualcuno mi saprebbe aiutare?
Grazie.
19 Aprile 2012
MaryMa se lo si volesse fare con la versione 4.3.2 dell’Xcode, dove non esiste la voce Navigation-based Application?
Sarò io che non ho molta praticità nel campo delle app e dell’Xcode, ma vorrei gentilmente sapere come fare,
grazie!!
12 Luglio 2012
MarioMa un database sqlite come può essere protetto? Ha la possibilità di utilizzare una password di accesso?
Inoltre se volessi condividere tramite cloud il database in modo da condividerlo con un’applicazione per mac, come potrei farlo?
14 Luglio 2012
salvociao,
volevo sapere se è possibile sommare gli elementi di una colonna della query e se si come.
E in generale se ad esempio ho un database con più tabelle, se è possibile raggruppare e filtrare i valori.
Ad esempio prima tabella formata da:
id – nome – punteggio
seconda tabella:
id – classe- scuola – numero allievi
e cosi via.
come faccio a fare sommare il punteggio e filtrare i dati in maniera personalizzata.
Vi ringrazio anticipatamente, siete veramente eccezionali.
7 Aprile 2013
DevTutorial #20 – Come implementare un database SQL - Bubi Devs[…] Leggi il tutorial completo su devAPP […]
8 Novembre 2013
Riccardocome faccio se voglio inserire un database sqlite esterno all’applicazione?
18 Novembre 2013
ignaziocnon puoi.
1 Febbraio 2014
Marco DeboCiao bel tutorial purtroppo a me non va.
Nel metodo caricaValoriDaDB la query non vengono restituiti i valori perchè il codice non entra mai nella condizione con il while.
Ho fatto i seguenti log per verificare la condizione dell’while.
NSLog(@”sqlite3_step %i” ,sqlite3_step(selectstmt)); viene 21
NSLog(@”sqlite_row %i”, SQLITE_ROW ); viene 100
Ho controllato anche il path ed è corretto.
22 Febbraio 2014
giovanniciao,
scusate la domanda…sono alle prime armi. E’ possibile interagire accedendo da un’app iphone a joomla?