Nelle applicazioni di tipo client-server, è fondamentale durante la lettura dei dati avere un meccanismo di paginazione, già alla fonte. Non è infrequente infatti trovare servizi poco ottimizzati che restituiscono ad ogni richiesta che l'applicazione effettua, una grande mole di dati, troppi per una singola visualizzazione. Questo comportamento genera due tipi di problemi:
- un traffico eccessivo tra applicazione e server, che in situazioni di scarsa copertura di rete può provocare attese o peggio degenerare in un timeout error,
- la ricezione di molti dati inutili all'applicazione, che magari è alla ricerca di un'unica e precisa informazione. In questo caso inoltre, dovremo implemetare nell'applicazione una logica per la ricerca tra i dati restituiti per ottenere l'informazione desiderata.
Un tipico esempio di questo comportamento è la funzione di ricerca: i dati ritornati dall'algoritmo di ricerca potrebbero essere veramente molti e restituirli tutti in blocco non è certo la soluzione ottimale.
La soluzione migliore è quella di restituire i risultati della ricerca in blocchi di dimensione prefissata: ad esempio ogni blocco contiene 10 risultati. In fin dei conti anche i più famosi motori di ricerca funzionano così: ogni pagina ha un numero fissato di link.
Per fare questo abbiamo bisogno di un servizio che prenda in input due parametri: uno per indicare l'indice del primo elemento che vogliamo ed un secondo per indicare l'indice dell'ultimo elemento. Ad esempio, nel caso volessimo una paginazione di 10 elementi alla volta, nella prima richiesta dovremo chiedere i risultati da 1 a 10, nella seconda da 11 a 20 e così via.
Per fare questo, all'interno dell'SDK abbiamo a disposizione l'oggetto MSQuery
, che ci permette di impostare questi limiti nelle richieste.
L'oggetto MSQuery
, come suggerisce il nome, è la rappresentazione all'interno del codice di una query da eseguire nel db del nostro servizio web. La classe non è "threadsafe" il che significa che non deve essere usata su dei thread secondari ma solo all'interno del main thread.
Le proprietà che ci interessano per la paginazione sono:
Proprietà | Descrizione |
---|---|
fetchOffset | indica l'indice del primo elemento restituito dalla query |
fetchLimit | indica il numero di elementi che vogliamo |
Inoltre useremo anche la proprietà includeTotalCount che servirà a far ritornare il numero totale di elementi presenti all'interno della tabella: in questo modo sapremo sempre quali elementi stiamo visualizzando e quanti ne mancano per la lettura completa della tabella.
Quindi, supponiamo di voler scaricare dal server solo i primi 3 dati presenti all'interno della tabella: dovremo impostare come elemento iniziale quello di indice 0:
query.fetchOffset = 0;
e poi impostare a 3 il numero di dati restituiti dal servizio:
query.fetchLimit = 3;
Il codice completo per eseguire questa paginazione è il seguente:
MSTable * table = [_theClient getTable:@"articleData"];
MSQuery * query = [[MSQuery alloc] initWithTable:table];
query.includeTotalCount = YES;
query.fetchOffset = 0;
query.fetchLimit = 3;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error) {
if (error)
{
NSLog(@"%@",error);
}
else
{
NSLog(@"items.count %i", items.count);
NSLog(@"totalCount %i",totalCount);
for (NSDictionary * anItem in items)
{
NSLog(@"%@", anItem);
}
}
}];
Vediamo ora come iterare questo procedimento in modo da rendere automatico il meccanismo e ad ogni richiesta richiedere le successive 3 righe della tabella. Portiamo dunque la tabella in uno stato simile a questo:
Quello che dobbiamo fare adesso è dichiarare un dato membro che conterrà il numero della prossima pagina da richiedere al server:
@property (nonatomic) int page;
Dopo aver inizializzato il valore della variabile page
all'interno del metodo di init
:
self.page = 0;
modifichiamo il metodo di inserimento nel seguente modo:
int size = 3;
MSTable * table = [_theClient getTable:@"articleData"];
MSQuery * query = [[MSQuery alloc] initWithTable:table];
query.includeTotalCount = YES;
query.fetchOffset = self.page * size;
query.fetchLimit = size;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error) {
if (error)
{
NSLog(@"%@",error);
}
else
{
NSLog(@"items.count %i", items.count);
NSLog(@"totalCount %i",totalCount);
for (NSDictionary * anItem in items)
{
NSLog(@"%@", anItem);
}
self.page++;
}
}];
Adesso, ad ogni nuova richiesta, riceveremo i successivi 3 elementi presenti nella tabella. In particolare alla prima richiesta riceveremo (ovviamente) i primi 3 elementi:
{
Anno = 1475;
Cognome = Buonarroti;
Nome = Michelangelo;
id = 1;
}
{
Anno = 1265;
Cognome = Alighieri;
Nome = Dante;
id = 11;
}
{
Anno = 1798;
Cognome = Leopardi;
Nome = Giacomo;
id = 12;
}
alla seconda richiesta gli elementi 4,5 e 6
{
Anno = 1451;
Cognome = Colombo;
Nome = Cristoforo;
id = 13;
}
{
Anno = 1454;
Cognome = Vespucci;
Nome = Amerigo;
id = 14;
}
{
Anno = 1807;
Cognome = Garibaldi;
Nome = Giuseppe;
id = 15;
}
e alla terza richiesta l'ultimo elemento.
{
Anno = 1874;
Cognome = Marconi;
Nome = Guglielmo;
id = 16;
}
Inviare mail con i componenti esterni dello store
In questa ultima lezione vedremo come aggiungere uno script sul server che ci permetterà di inviare email tramite il servizio cloud SendGrid. Alla fine della lezione, tutte le volte che verrà inserito un record all'interno della tabella, sarà inviata un'email all'indirizzo prestabilito contenente informazioni relative al record appena inserito.
SendGrid è un affidabile servizio email basato su tecnologia cloud, molto scalabile e offre statistiche real-time sull'utilizzo. Maggiori informazioni possono essere trovate sul sito sendgrid.com.
Vedremo dunque come creare un account SendGrid, aggiungere lo script per l'invio delle email e inserire dati in modo da ricevere le email.
Creare un account SendGrid
Per prima cosa dobbiamo crearci un account SendGrid. Andiamo sul Windows Azure Management Portal ed eseguiamo l'accesso. In basso a sinistra selezioniamo la voce + Nuovo.
Selezioniamo la voce Negozio
:
Nel menu successivo scegliamo SendGrid e poi premiamo sulla freccia in basso a destra.
Selezioniamo il piano Bronzo
, inseriamo il codice promozionale freesendgridbronze
(offerto a tutti gli utenti Azure che permette di usufruire di due mesi gratuiti dell'account Bronzo) e poi il nome per poter identificare il servizio SendGrid. Potete anche utilizzare il nome di default SendGrid
, l'importante è che contenga un numero di caratteri compresi tra 1 e 100 e contenga solo caratteri alfanumerici, trattini, punti e underscores.
Premiamo nuovamente sulla freccia in basso a destra e nel menu di riepilogo clicchiamo sul simbolo di spunta accetto.
Una volta creato il servizio, selezioniamo in basso la voce informazioni di connessione e nella pagina successiva copiamoci la username e la password che ci serviranno successivamente.
Impostare uno script per l'invio delle email
Adesso dobbiamo scrivere lo script che, collegandosi tramite la nostra username e password, al servizio SendGrid appena creato invierà la mail ogni volta che sarà inserito un record all'interno della tabella.
Portiamoci nella sezione relativa agli script (come abbiamo visto nelle lezioni precedenti) e selezioniamo dal menu a tendina l'operazione Inserisci. Dovremo sostituire il codice di default:
function insert(item, user, request) {
request.execute();
}
con il seguente:
var SendGrid = require('sendgrid').SendGrid;
function insert(item, user, request) {
request.execute({
success: function() {
request.respond();
sendEmail(item);
}
});
function sendEmail(item) {
var sendgrid = new SendGrid('**username**', '**password**');
sendgrid.send({
to: '**email-to**',
from: '**email-from**',
subject: 'Nuovo messaggio inviato con SendGrid',
text: 'Inserita nuova riga: ' + item.Nome + ',' + item.Cognome + '!'
}, function(success, message) {
if (!success) {
console.error(message);
}
});
}
}
Al posto dei placeholder dovrete inserire:
Placeholder | Descrizione |
---|---|
**username**: |
lo username che abbiamo recuperato dalla pagina informazioni di connessione |
**password**: |
la password che abbiamo recuperato dalla pagina informazioni di connessione |
**email-to**: |
l'indirizzo email al quale inviare l'email |
**email-from**: |
l'indirizzo email dal quale l'email sarà generata. Usate l'indirizzo SendGrid appena creato che sarà del tipo notifications@nome-del-servizio.azure-mobile.net. In questo caso, sarà notifications@sendgrid.azure-mobile.net |
Inserimento nuovi record all'interno della tabella
Ora non resta che provare ad inserire un nuovo record all'interno della tabella per ricevere l'email di notifica. Eseguiamo il solito codice per l'inserimento:
MSClient * theClient = [MSClient clientWithApplicationURLString:@"https://articles.azure-mobile.net/" withApplicationKey:@"cczdHhxDHtVaPqhMjgpfdGpiiBUiuusM62"];
MSTable * table = [theClient getTable:@"articleData"];
NSDictionary *item = @{
@"Nome" : @"Antonio",
@"Cognome" : @"Meucci",
@"Anno" : @1808
};
[table insert:item parameters:nil completion:^(NSDictionary *item, NSError *error) {
if (error) {
NSLog(@"%@", error.localizedDescription);
}
else
{
NSLog(@"Insert");
}
}];
Se tutti i dati inseriti sono corretti, dopo qualche istante riceverete una mail sull'indirizzo specificato che vi avviserà che un nuovo record è stato inserito. all'interno della tabella.