Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Cloud, Dropbox e applicazioni iOS

Realizzare un'applicazione iOS per interagire con i servizi di cloud storage di Dropbox: inserire nell'interfaccia utente opzioni per salvare, leggere e cancellare file
Realizzare un'applicazione iOS per interagire con i servizi di cloud storage di Dropbox: inserire nell'interfaccia utente opzioni per salvare, leggere e cancellare file
Link copiato negli appunti

In questo articolo realizzeremo un'applicazione iOS per interagire con i servizi di cloud computing offerti dal servizio di storage online Dropbox. Vedremo come caricare file in the cloud, come leggerli, come cercarli, come cancellarli e così via. Prima di entrare nel vivo dell'articolo, è bene analizzare il contesto in cui la nostra applicazione si colloca, analizzando velocemente i temi che andremo ad affrontare.

Una premessa: l'articolo è pensato per un utilizzo pratico. Faremo dunque riferimento a istruzioni passo per passo su come creare ogni singolo componente della nostra applicazione. Per questo è necessario avere almeno le basi di programmazione per iOS, basi che è facile acquisire leggendo le prime lezioni della nostra guida alla creazione di applicazioni per iPhone e iPad. Tutti i file che utilizzeremo saranno scaricabili liberamente attraverso il link a fondo articolo.

Cloud computing e Dropbox

Con cloud computing identifichiamo, con un po' di approssimazione, un insieme di funzionalità fornite online che ci permettono di salvare, recuperare ed elaborare dati. Uno dei maggiori vantaggi è rappresentato dalla disponibilità delle risorse: si può accedere a dati e applicazioni da qualsiasi luogo poiché essi sono conservati nei server del provider e non sulla macchina del cliente. Un banale esempio di servizio fornito in cloud computing è quello delle webmail (tipo Gmail): accessibili da qualsiasi dispositivo con un semplice browser.

Tra i servizi di cloud computing, uno dei più diffusi è quello della condivisione e sincronizzazione di file su storage online. Tra questi servizi, Dropbox è sicuramente il più famoso, e meritatamente.

Ai fini del nostro scopo, la funzionalità che ci tornerà più utile è il suo essere multipiattaforma: Dropbox offre l'accesso ai contenuti tramite browser, ma soprattutto mette a disposizione un'applicazione per i più diffusi sistemi operativi sia desktop, sia mobile. In questo modo i nostri file non saranno solo accessibili via web, ma, una volta acceso il nostro computer o il nostro smartphone, potranno essere sincronizzati online.

Poiché utilizzeremo per la nostra applicazione le API di Dropbox, per il prosieguo dell'articolo è necessario avere un account attivo su questo servizio.

L'applicazione iOS demo

L'applicazione iOS che realizzeremo permetterà la fruizione e la modifica delle risorse presenti in una cartella Dropbox. L'applicazione sarà formata delle seguenti tre pagine:

  • Una pagina di login per sfruttare l'applicazione Dropbox nativa ed eseguire il login con il nostro account.
  • Una pagina in cui sarà possibile recuperare la lista dei file presenti in una cartella, creare una nuova cartella, cancellare un file o una cartella, scaricare un documento, effettuare l'upload di un file ed eseguire una ricerca all'interno di una cartella.
  • Una pagina, contenete un oggetto di tipo UIWebView (componente di sistema che consente la visualizzazione di risorse web, immagini, files pdf e molto altro), che ci consentirà di mostrare un file precedentemente scaricato.

Registrare l'app su Dropbox

La prima operazione da fare è registrare la nostra applicazione in Dropbox. Per far ciò andiamo sulla home page per sviluppatori Dropbox e, nel menu di sinistra della pagina, facciamo sulla voce My apps. Se è la prima volta che accedete alla sezione, vi sarà chiesto di accettare i termini della licenza. Una volta attivi, all'interno di questa pagina potremo sia creare una nuova applicazione, sia gestire le applicazioni già esistenti.

Creiamo dunque la nostra applicazione cliccando sul bottone Create an App:

Figura 01. Pagina My Apps per sviluppatori
(clic per ingrandire)


Pagina My Apps per i developers

Si aprirà una pop-up come quella rappresentata nella figura sotto:

Figura 02. Pagina per la creazione di una nuova applicazione di Dropbox
(clic per ingrandire)


Pagina per la creazione di una nuova applicazione di Dropbox

Tutti i campi mostrati nel form di registrazione sono obbligatori:

  • App name: è il nome dell'applicazione.
  • Description: è la descrizione associata all'applicazione che stiamo creando.
  • Access Level: è il tipo di accesso che viene consentito all'applicazione.

Su quest'ultima opzione: se si spunta la prima opzione (App folder), l'applicazione avrà accesso esclusivamente ad una cartella (che verrà creata in automatico con il nome dell'applicazione) collegata all'utente che abbiamo utilizzato per creare l'applicazione. Se invece si spunta la seconda opzione (Full Dropbox) si permette l'accesso a tutte le cartelle associate all'account. Scegliamo questa seconda opzione perché consentirà di lavorare su cartelle condivise tra utenti, a differenza della prima che lavora solamente su una specifica cartella che non può essere condivisa con altri utenti.

Cliccando su Create viene creata l'applicazione e, dopo qualche secondo, si viene portati alla pagina web relativa all'applicazione stessa. Come possiamo vedere la pagina è composta da diverse sezioni; analizziamo le principali.

HTMLCloud

Figura 03. Sezione principale relativa alla pagina di un'applicazione Dropbox
(clic per ingrandire)


Sezione principale relativa alla pagina di un'applicazione Dropbox

All'interno di questa sezione vengono riportati il nome dell'applicazione, il tipo di accesso che abbiamo impostato ed inoltre lo stato dell'applicazione. Quest'ultimo campo, come possiamo vedere dalla figura sopra, riporta il valore development; nel caso in cui si voglia rendere pubblica tale applicazione sarà necessario inviare una richiesta di pubblicazione.

Andando oltre possiamo vedere che sono presenti altri due campi (AppKey e AppSecret), fondamentali nello sviluppo dell'applicazione iOS per stabilire una connessione con i servizi Dropbox.

Additional users

Figura 04. Sezione Additional users relativa alla pagina di un'applicazione Dropbox
(clic per ingrandire)


Sezione Additional users relativa alla pagina di un'applicazione Dropbox

L'utilizzo dell'applicazione, all'atto della sua creazione, viene consentito solo all'account con cui è stata creata. Ciò vuol dire che non sarà  possibile utilizzarla se eseguiremo il login utilizzando un altro utente. Per rendere l'applicazione multi-utente è sufficiente cliccare sul link Enable multi users e, nella finestra pop-up, che apparirà confermare con un clic sul bottone Enable (figura sotto).

Figura 05. Pop-up di conferma per l'abilitazione del multi-users
Pop-up di conferma per l'abilitazione del multi-users

Durante il processo di sviluppo è consentito l'utilizzo simultaneo dell'applicazione solo a cinque account Dropbox differenti.

A questo punto la configurazione della nostra prima applicazione Dropbox è conclusa. L'ultima operazione che è necessario eseguire è la creazione di una cartella con nome HTMLCloud (non necessariamente deve avere lo stesso nome dell'applicazione Dropbox) nella root della gerarchia di cartelle dell'account Dropbox e condividere tale cartella con gli altri account che useremo per eseguire lo sviluppo dell'applicazione.

SDK di Dropbox e Xcode

Terminate le operazioni preliminari, siamo pronti ad integrare all'interno di un nostro progetto Xcode l'SDK di Dropbox (per le basi della programmazione iOS e l'uso di Xcode si rimanda alla nostra guida alla creazione di applicazioni per iPhone e iPad).

Andiamo dunque alla pagina dei download nella sezione developer di Dropbox ed ovviamente, tra gli SDK offerti, selezioniamo quello relativo ad iOS. Terminato il download del file in formato zip, decoprimiamolo e, al suo interno, identifichiamo la cartella DropboxSDK.framework che rappresenta l'SDK di sviluppo ed è quella che andremo ad importare nel nostro progetto Xcode.

Apriamo dunque l'IDE di sviluppo, scegliamo come template di partenza Empty Application e creiamo un nuovo progetto come segue:

Figura 06. Creazione del progetto HTMLCloud su Xcode
(clic per ingrandire)


Creazione del progetto HTMLCloud su Xcode

Scegliamo come nome HTMLCloud, come Device Family scegliamo iPhone ed infine spuntiamo il check box relativo all'Automatic Reference Count, il quale ci assolverà da dover inserite chiamate splicite ai metodi release o retain sui vari oggetti.

A questo punto torniamo all'interno della cartella relativa all'SDK di Dropbox precedentemente scaricata e, con un drag-and-drop del mouse, importiamo la cartella DropboxSDK.framework all'interno del progetto (nella schermata che apparirà dopo il drop del framework spuntare l'opzione Copy items into destination group's folder).

C'è da notare subito una cosa: se provassimo ad effettuare ora un build del progetto  otterremo diversi errori. Questo perché il framework Dropbox utilizza altri due framework iOS: QuartzCore.framework e Security.framework. Per aggiungere un nuovo framework al progetto clicchiamo sulla root dell'albero di navigazione del progetto nella parte sinistra di Xcode, selezioniamo HTMLCloud come Target ed infine sul tab Build phases.

Figura 07. Aggiunta di un framework iOS ad un progetto Xcode
(clic per ingrandire)


Aggiunta di un framework iOS ad un progetto Xcode

Esploriamo dunque la sezione Link Binary With Libraries e clicchiamo sul tasto "+". Nella nuova finestra che compare selezioniamo uno dei due framework necessari che abbiamo elencato precedentemente e clicchiamo su Add. Ripetendo l'operazione anche per il secondo framework mancante, la configurazione finale dell'albero di navigazione del progetto sarà la seguente:

Figura 08. Framework necessari aggiunti al progetto Xcode
Framework necessari aggiunti al progetto Xcode

Il lavoro di importazione e configurazione iniziale del framework di Dropbox è terminato. Effettuando adesso un Build del progetto l'operazione verrà eseguita senza nessun problema.

Creare la pagina di Login

Siamo pronti per sviluppare la nostra applicazione. In questa lezione andremo a realizzare la pagina iniziale che consentirà le seguenti operazioni:

  • Login/Logout al servizio di Dropbox.
  • Accesso alla cartella HTMLCloud dell'applicazione.

Spostiamo subito l'attenzione all'interno del file AppDelegate.m, il file che rappresenta il punto iniziale del flusso d'esecuzione dell'applicazione. Subito dopo le direttive di import definiamo le seguenti due costanti:

#import <DropboxSDK/DropboxSDK.h> 
#define APPKEY @"2sjagz8grla0nyi"
#define APPSECRET @"xx7e1fmvq6g8t28"

I valori relativi ad APPKEY e APPSECRET sono naturalmente gli stessi che abbiamo visto nella precedente lezione quando abbiamo creato l'applicazione nella sezione developer di Dropbox. Ovviamente assicuratevi che i valori inseriti siano corretti, altrimenti non sarà possibile instaurare una connessione con i servizi Dropbox.

Adesso spostiamoci nel metodo application: didFinishLaunchingWithOptions: e, dopo la definizione del frame della window, inseriamo le seguenti linee di codice:

DBSession* dbSession = [[DBSession alloc] initWithAppKey:APPKEY appSecret:APPSECRET root:kDBRootDropbox];
[DBSession setSharedSession:dbSession];

La classe DBSession è la prima classe dell'SDK di Dropbox che introdurremo. Questa classe permette l'avvio di una sessione con i servizi di Dropbox effettuando un controllo sui valori di APPKEY e APPSECRET forniti dallo sviluppatore. Vedremo più avanti in questa lezione come usare questa sessione per effettuare il login con un utente.

Abbandoniamo adesso il file AppDelegate.m e, dato che abbiamo scelto un progetto di tipo Empty Application, avremo, nella nostra gerarchia di file e cartelle di progetto, solo il file AppDelegate. Aggiungiamo dunque un nuovo file, scegliamo come template UIViewController subclass (che in automatico inseririrà, nella definizione della nuova classe, la derivazione dalla classe UIViewController) e chiamiamolo MenuViewController.

Spostiamoci poi nel file MenuViewController.h e creiamo ("dichiariamo", in linguaggio di programmazione) due bottoni che svolgeranno l'operazione di login/logout e l'accesso alla cartella condivisa:

UIButton *_linkButton;
UIButton *_enterButton;

A questo punto spostiamoci nel file MenuViewController.m e, come prima cosa, importiamo l'SDK di Dropbox come segue:

#import <DropboxSDK/DropboxSDK.h>

Infine dichiariamo il seguente metodo di init:

- (id)init
{
    self = [super init];
    if (self) {
        self.view.backgroundColor = [UIColor whiteColor];
        UIImageView *htmlLogo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logoHTML.jpg"]];
        [self.view addSubview:htmlLogo];
        _linkButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _linkButton.frame = CGRectMake(10, 150, 300, 60);
        [_linkButton setTitle:@"Accedi con account Dropbox" forState:UIControlStateNormal];
        [_linkButton addTarget:self action:@selector(didPressLink) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_linkButton];
        _enterButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _enterButton.frame = CGRectMake(10, 250, 300, 60);
        [_enterButton setTitle:@"Entra nella cartella dell'applicazione" forState:UIControlStateNormal];
        [_enterButton addTarget:self action:@selector(showDropboxFolder) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_enterButton];
        [self updateButtonsLabelWithState:[[DBSession sharedSession] isLinked]];
    }
    return self;
}

Nel metodo di init creiamo semplicemente un'immagine (contenente il logo di HTML.it) e i due pulsanti che svolgeranno le funzioni viste precedentemente.

Da notare, nell'ultima riga di codice, l'accesso alla propertyisLinked del DBSession. Tale property restituisce un valore booleano: YES se è già stato eseguito il login con un account Dropbox e NO se ciò non è avvenuto.

Nel codice indicato sopra abbiamo inoltre associato al bottone _linkButton il metodo didPressLink che si occuperà di svolgere la funzione di login/logout e al bottone _enterButton il metodo showDropboxFolder che consentirà l'accesso alla cartella condivisa Dropbox.

Per dichiararli, sempre nel file MenuViewController.m, prima della direttiva @implementation MenuViewController, implementiamo i seguenti metodi privati:

@interface MenuViewController(private)
- (void)showDropboxFolder;
- (void)didPressLink;
@end
@implementation MenuViewController(private)
- (void)showDropboxFolder
{
}
- (void)didPressLink
{
    if (![[DBSession sharedSession] isLinked]) {
        [[DBSession sharedSession] linkFromController:self];
    }
    else {
        [[DBSession sharedSession] unlinkAll];
        [self updateButtonsLabelWithState:NO];
    }
}
@end

Il metodo showDropboxFolder verrà completato nella prossima lezione, mentre vale la pena analizzare da subito il codice all'intero del metodo didPressLink.

Prima di tutto, per differenziare l'operazione di login da quella di logout, utilizziamo la property isLinked della classe DBSession. Per effettuare il login richiamiamo il metodo linkFromController: che eseguirà la seguente operazione: se è installata sul dispositivo, verrà richiamata l'applicazione Dropbox per permettere il login al suo interno; altrimenti verrà aperta una pagina web all'interno della nostra stessa applicazione per consentire la medesima operazione. Per disconnettere l'utente utilizziamo il metodo unlinkAll.

A questo punto la scrittura del MenuViewController è quasi terminata: ci rimane solo la dichiarazione del metodo updateButtonsLabelWithState: che si occupa semplicemente di cambiare il testo contenuto nel bottone _linkButton. Andiamo dunque nel file MenuViewController.h ed inseriamo la seguente linea di codice:

- (void)updateButtonsLabelWithState:(BOOL)linked;

Spostiamoci poi nel metodo MenuViewController.m ed implementiamo il metodo come segue:

- (void)updateButtonsLabelWithState:(BOOL)linked
{
    if (linked) {
        _enterButton.enabled = YES;
        [_enterButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_linkButton setTitle:@"Disconnetti account Dropbox" forState:UIControlStateNormal];
        [_linkButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    }
    else {
        _enterButton.enabled = NO;
        [_enterButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal];
        [_linkButton setTitle:@"Accedi con account Dropbox" forState:UIControlStateNormal];
        [_linkButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    }
}

A questo punto il lavoro sulla classe MenuViewController è terminato. Spostiamoci adesso nel file AppDelegate.h nel quale andremo a dichiarare un oggetto di tipo MenuViewController.

Per prima cosa, importiamo il file MenuViewController.h. Dichiariamo poi un oggetto di tipo MenuViewController come segue:

MenuViewController *_menuVC;

Spostiamoci nel file AppDelegate.m e nel metodo application:didFinishLaunchingWithOptions: inseriamo il seguente codice dopo la dichiarazione del DBSession:

MenuViewController * menuVC = [[MenuViewController alloc] init];
self.window.rootViewController = menuVC;

Ultima modifica da apportare al file AppDelegate.m è l'inserimento del seguente metodo:

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    if ([[DBSession sharedSession] handleOpenURL:url]) {
        if ([[DBSession sharedSession] isLinked]) {
            [_menuVC updateButtonsLabelWithState:YES];
        }
        return YES;
    }
    return NO;
}

Tale metodo verrà richiamato una volta terminato il login all'interno dell'applicazione Dropbox o tramite la pagina web (mostrata nel caso in cui sul dispositivo non sia installata l'app di Dropbox).

Adesso è necessario eseguire l'ultima, ma fondamentale, configurazione al nostro progetto. Selezioniamo il file HTMLCloud-Info.plist e, con un clic destro, selezioniamo Open As ed infine clicchiamo su Source Code:

Figura 09. Visualizzazione del file di configurazione HTMLCloud-Info.plist in modalità Source Code
Visualizzazione del file di configurazione HTMLCloud-Info.plist in modalità Source Code

Verrà mostrato HTMLCloud-Info.plist in una sintassi XML. Dopo il tag <dict> incolliamo il seguente codice:

<key>CFBundleURLTypes</key>
<array>
    <dict>
	    <key>CFBundleURLSchemes</key>
	    <array>
	        <string>db-2sjagz8grla0nyi</string>
	    </array>
	</dict>
</array>

Questa direttiva è necessaria per consentire il login tramite l'applicazione Dropbox nativa e richiamare nuovamente la nostra applicazione una volta terminato il login (naturalmente nel campo <string> dovete sostituire l'APPKEY di esempio con quello della vostra applicazione Dropbox).

A questo punto siamo pronti per effettuare il primo Run del progetto. La schermata di login sarà la seguente:

Figura 10. Schermata di menu quando non è ancora stato eseguito il Login
(clic per ingrandire)


Schermata di menu quando non è ancora stato eseguito il Login

Se tocchiamo il pulsante Accedi con account Dropbox, la nostra applicazione andrà in background e comparirà l'applicazione Dropbox (se installata) come nella seguente figura (operazione permessa grazie alla direttiva inserita all'interno del file HTMLCloud-Info.plist):

Figura 11. Applicazione Dropbox per la connessione ai servizi
(clic per ingrandire)


Applicazione Dropbox per la connessione ai servizi

Tocchiamo dunque il tasto Allow e, dopo qualche istante, vedremo ricomparire la nostra applicazione (operazione permessa sempre grazie alla direttiva inserita all'interno del file HTMLCloud-Info.plist) e, se il login è andato a buon fine, la schermata principale apparirà nel seguente modo:

Figura 12. Schermata di menu quando è stato eseguito il Login
(clic per ingrandire)


Schermata di menu quando è stato eseguito il Login

Recupero dei file da Dropbox: l'oggetto DBRestClient

Entriamo nel vivo della trattazione andando a mostrare il codice necessario per acquisire la lista di file presente all'interno di una cartella Dropbox.

In questa lezione andremo ad introdurre la classe più importante dell'SDK di Dropbox e vedremo,
utilizzando i metodi di delegato associati a questa classe, come effettuare le chiamate ai servizi di
Dropbox e gestire le informazioni che ci vengono ritornate come risposta alla nostra chiamata.

Come prima cosa creiamo un nuovo file (scegliendo sempre come template UIViewController subclass) e nominiamolo HierarchyViewController.

Spostiamoci nel file HierarchyViewController.h e dichiariamo il seguente bottone come attributo di classe:

UIButton *_showFilesListButton;

Spostiamoci nel file HierarchyViewController.m e dichiariamo il seguente metodo di init con al suo interno la dichiarazione del bottone precedentemente dichiarato:

- (id)init{
    self = [super init];
    if (self) {
        self.view.backgroundColor = [UIColor whiteColor];
        _showFilesListButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _showFilesListButton.frame = CGRectMake(10, 30, 300, 40);
        [_showFilesListButton setTitle:@"Lista files" forState:UIControlStateNormal];
        [_showFilesListButton addTarget:self action:@selector(didPressShowFiles) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:_showFilesListButton];
    }
}

A questo punto è necessario dichiarare il metodo didPressShowFiles come metodo privato (ovviamente lo si può dichiarare anche come metodo pubblico) andando ad inserire il seguente codice prima della direttiva @implementation HierarchyViewController:

@interface HierarchyViewController(private)
- (void)didPressShowFiles;
@end
@implementation HierarchyViewController(private)
- (void)didPressShowFiles{
}
@end

Arrivati a questo punto dovremmo implementare il metodo didPressShowFiles, ma lo faremo dopo perché è arrivato il momento di introdurre la classe che gestisce tutte le chiamate con i servizi di Dropbox: il DBRestClient.

Tale classe provvede ad effettuare chiamate di tipo asincrono ai servizi di Dropbox e permette allo sviluppatore di conoscere l'esito della chiamata semplicemente implementando il protocollo DBRestClientDelegate. Questo protocollo, per ogni metodo (ossia per ogni azione sulla nostra cartella condivisa su Dropbox) mette a disposizione due metodi: uno che viene richiamato se l'operazione è andata a buon fine e un altro che viene richiamato se l'operazione non è andata a buon fine e si è dunque verificato un errore. Solo nei metodi di upload e di download abbiamo a disposizione un terzo metodo di delegato che ci consente di conoscere lo stato di avanzamento relativo al download o all'upload

Fatta questa breve introduzione, andiamo a mostrare il codice necessario per scaricare la lista di elementi presenti nella cartella HTMLCloud. Spostiamoci nel file HierarchyViewController.h ed implementiamo il protocollo DBRestClientDelegate come segue (ovviamente prima inseriamo la seguente linea di codice: #import <DropboxSDK/DropboxSDK.h>)

@interface HierarchyViewController : UIViewController <DBRestClientDelegate>

Sempre nel file HierarchyViewController.h dichiariamo il seguente attributo:

DBRestClient *_restClient;

A questo punto spostiamoci nel file HierarchyViewController.m ed aggiungiamo le seguenti linee di codice nel metodo di init (inserito precedentemente) prima della dichiarazione del _showFilesListButton:

_showFilesListButton:
- (id)init {
  _restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
  _restClient.delegate = self;
}

Come possiamo vedere allochiamo l'oggetto _restClient passando come parametro il DBSession che abbiamo visto nella precedente lezione e indichiamo come delegato self. Ciò ci consentirà di implementare i metodi di delegato direttamente nella classe HierarchyViewController.

Adesso nel metodo didPressShowFiles, sempre nel file HierarchyViewController.m, inseriamo la seguente linea di codice:

[_restClient loadMetadata:@"/HTMLCloud"];

L'invocazione al metodo loadMetadata: ci permetterà  di acquisire la lista dei file contenuti all'interno del path passato come parametro (nel nostro caso passiamo come parametro la cartella HTMLCloud che avevamo creato e condiviso precedentemente).

A questo punto implementiamo, sempre nel file HierarchyViewController.m, i metodi di delegato di cui abbiamo bisogno:

- (void)restClient:(DBRestClient *)client loadedMetadata:(DBMetadata *)metadata
{
	UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Lista files" message:@"Lista file acquisita con successo" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
	NSLog(@"Folder '%@' contains:", metadata.path);
   	for (DBMetadata *file in metadata.contents) {
            NSLog(@"%@", file.filename);
	}
}
- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error
{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Attenzione!" message:@"Impossibile acquisire la lista dei files" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"%@", error);
}

Nel primo metodo (richiamato se non ci sono stati errori) viene restituito un oggetto di tipo DBMetadata i cui attributi principali sono i seguenti:

  • filename: rappresenta il nome del file o cartella.
  • isDirectory: ci informa se il file è una cartella o un file generico.
  • contents: è un array che al suo interno contiene oggetti di tipo DBMetadata. In questo modo abbiamo a disposizione l'intera gerarchia di cartelle e file presenti nella cartella attualmente scaricata.

All'interno di questo metodo di delegato semplicemente stampiamo sulla console la lista di file e cartelle contenute all'interno della cartella HTMLCloud e mostriamo a schermo un avviso.

Il lavoro sullo HierarchyViewController.m è terminato. Torniamo nel file MenuViewController.m ed importiamo la classe HierarchyViewController:

#import "HierarchyViewController.h"

Spostiamoci nel metodo showDropboxFolder e popoliamolo con il seguente codice:

HierarchyViewController *hierarchyVC = [[HierarchyViewController alloc] init];
[self presentModalViewController:hierarchyVC animated:YES];

A questo punto eseguiamo un Run del progetto, premiamo il bottone per visualizzare il contenuto della cartella Dropbox e poi premiamo il pulsante Lista Files; vedremo comparire, sulla console, la lista dei file contenuti nella cartella HTMLCloud (i file senza estensione sono delle cartelle). .

Figura 13. Console con l'elenco dei file della cartella Dropbox
Screenshot della console che mostra la lista dei file contenuti all'interno della cartella Dropbox

Il percorso che abbiamo passato al metodo loadMetadata: faceva riferimento alla nostra cartella root del progetto. Per esplorare sottocartelle presenti nella cartella root è sufficiente indicare il percorso nel path, come nel codice seguente:

[_restClient loadMetadata:@"/HTMLCloud/ApplicazioneDemo/Prova"];

Creazione di una nuova cartella

Vediamo come aggiungere una nuova cartella all'interno della cartella HTMLCloud. Per  prima cosa torniamo nel file HierarchyViewController.h e creiamo un nuovo pulsante:

UIButton *_createFolderButton;

Spostiamoci nel file HierarchyViewController.m e inizializziamo il pulsante sempre nel metodo di init:

_createFolderButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_createFolderButton.frame = CGRectMake(10, 100, 300, 40);
[_createFolderButton setTitle:@"Crea Cartella" forState:UIControlStateNormal];
[_createFolderButton addTarget:self action:@selector(didPressCreateFolder) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_createFolderButton];

A questo punto dichiariamo il metodo privato didPressCreateFolder ed inseriamo la sua implementazione:

-(void)didPressCreateFolder{
	NSString * pathDir = [NSString stringWithFormat:@"/HTMLCloud/MiaCartella/"];
    NSString * folderName = [NSString stringWithFormat:@"NuovaCartella"];
    [_restClient createFolder:[NSString stringWithFormat:@"%@%@", pathDir, folderName]];
}

Come possiamo vedere abbiamo creato due stringe: una rappresenta la directory nella quale verrà creata la nuova cartella (pathDir), un'altra il nome della cartella che vogliamo creare (folderName). Infine passiamo la concatenazione di queste due stringe al metodo createFolder:.

Nel caso in cui il percorso espresso nella stringa pathDir non esistesse (ossia, seguendo l'esempio, quando non esiste la cartella MiaCartella), tale percorso verrà creato automaticamente: verrà creata prima la cartella MiaCartella ed al suo interno la cartella NuovaCartella.

Adesso implementiamo, sempre nella classe HierarchyViewController.m, i seguenti metodi di delegato per conoscere l'esito della chiamata ai servizi di Dropbox:

- (void)restClient:(DBRestClient *)client createdFolder:(DBMetadata *)folder
{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Creazione cartella" message:@"Creazione cartella eseguita con successo!" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
}
- (void)restClient:(DBRestClient *)client createFolderFailedWithError:(NSError *)error
{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Attenzione!" message:@"Cartella già presente" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"%@", error);
}

Nel caso in cui sia già presente una cartella con lo stesso nome della cartella che si vuole creare verrà richiamato il metodo di delegato restClient: createFolderFailedWithError:.

Cancellazione di un file o una cartella

Vediamo adesso come cancellare un file o una cartella presente sulla nostra cartella condivisa Dropbox.  Come al solito, apriamo il file HierarchyViewController.h e dichiariamo un nuovo bottone:

UIButton *_deleteFolderOrFileButton;

Nel file HierarchyViewController.m inseriamo la dichiarazione del nuovo pulsante, sempre nel metodo di init:

_deleteFolderOrFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_deleteFolderOrFileButton.frame = CGRectMake(10, 180, 300, 40);
[_deleteFolderOrFileButton setTitle:@"Cancella cartella o file" forState:UIControlStateNormal];
[_deleteFolderOrFileaddTarget:self action:@selector(didPressDeleteButton) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_deleteFolderOrFileButton];

Dichiariamo il metodo privato didPressDeleteButton ed implementiamolo come segue (sempre nel file HierarchyViewController.m):

NSString * pathDir = [NSString stringWithFormat:@"/HTMLCloud/MiaCartella/"];
NSString * filename = [NSString stringWithFormat:@"NuovaCartella"];
[_restClient deletePath:[NSString stringWithFormat:@"%@%@", pathDir, filename]];

Anche in questo caso è sufficiente una sola linea di codice per cancellare una risorsa (file o cartella) indicata dal path passato come parametro (effettuiamo la stessa concatenazione di stringe vista nella precedente lezione).

Come per le altre chiamate viste precedentemente, implementiamo i due metodi di delegato di cui abbiamo bisogno, per conoscere l'esito della chiamata ai servizi di Dropbox:

- (void)restClient:(DBRestClient *)client deletedPath:(NSString *)path
{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Cancellazione cartella" message:@"Cancellazione cartella eseguita con successo" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"Deleted path %@", path);
}
- (void)restClient:(DBRestClient *)client deletePathFailedWithError:(NSError *)error
{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Attenzione!" message:@"Il file non esiste" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"%@", error);
}

Ovviamente, nel caso in cui si richiedesse la cancellazione di una risorsa non presente nella cartella Dropbox, verrà richiamato il metodo di delegato restClient: deletePathFailedWithError: che ci notificherà tale errore.

Download e visualizzazione di un documento

A questo punto possiamo abilitare l'applicazione al download, alla visualizzazione e all'upload di un documento presente nella nostra cartella condivisa Dropbox. In questa lezione ci occuperemo delle prime due operazioni, la terza la vedremo nella lezione successiva.

Nei prossimi paragrafi vedremo dunque come eseguire le seguenti operazioni:

  • Download della risorsa utilizzando un metodo del restClient.
  • Definizione di una path nella cartella Documenti dove verrà salvata la risorsa.
  • Visualizzazione del file all'interno di una UIWebView, oggetto di sistema che ci consente di visualizzare, in maniera molto semplice, oltre a pagine HTML anche file di estensione png, jpg, pdf e molto altro.
  • Cancellazione della risorsa dalla cartella Documenti una volta terminato il caricamento nella UIWebView.

Come prima cosa abbiamo bisogno di un nuovo ViewController che chiameremo DocumentViewController. Andiamo nel file DocumentViewController.h ed inseriamo il seguente codice:

#import <DropboxSDK/DropboxSDK.h>
@interface DocumentViewController : UIViewController <DBRestClientDelegate,UIWebViewDelegate>{
    UIWebView *_webView;
    DBRestClient *_restClient;
    NSString *_filePath;
}
- (void)back;

Spostiamoci adesso nel file DocumentViewController.m ed inseriamo il seguente codice:

- (id)init
{
    self = [super init];
    if (self) {
        self.view.backgroundColor = [UIColor whiteColor];
        UIToolbar * _toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)];
        _toolbar.barStyle = UIBarStyleBlack;
        [self.view addSubview:_toolbar];
        UIBarButtonItem * item = [[UIBarButtonItem alloc]initWithTitle:@"Indietro" style:UIBarButtonItemStyleBordered target:self action:@selector(back)];
        _toolbar.items = [NSArray arrayWithObject:item];
        _webView = [[UIWebView alloc] initWithFrame: CGRectMake(0, 44, 320, 480)];
        _webView.delegate = self;
        [self.view addSubview:_webView];
        _restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
        _restClient.delegate = self;
         NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        _filePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"logoHTML.jpg"]];
        NSString *dropboxPath = [NSString stringWithFormat:@"/HTMLCloud/logoHTML.jpg"];
        [_restClient loadFile:dropboxPath intoPath:_filePath];
    }
    return self;
}
- (void)back{
    [self dismissModalViewControllerAnimated:YES];
}

Concentriamo la nostra attenzione nella parte finale del metodo di init (in quanto le prime linee fanno riferimento semplicemente all'allocazione di una UIToolbar e di un UIBarButtonItem). Quello che facciamo è salvare il percorso relativo alla cartella Documenti in cui verrà copiata la risorsa scaricata (salvata nella variabile _filePath) e richiamare il metodo loadFile: intoPath: passando come parametri il percorso della risorsa relativa alla cartella Dropbox (dropboxPath) e quello in cui verrà salvata la risorsa.

Il metodo back viene utilizzato per tornare al menu principale dell'applicazione ed effettuare dunque il dismiss (ovvero la rimozione del ViewController dallo schermo) del DocumentViewController.

Vediamo come gestire il download della risorsa (sempre nel file DocumentViewController.m)

- (void)restClient:(DBRestClient *)client loadedFile:(NSString *)destPath
{
    NSURL *url = [NSURL URLWithString:destPath];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    [_webView loadRequest:request];
}
- (void)restClient:(DBRestClient *)client loadFileFailedWithError:(NSError *)error{
    NSLog(@"%@", error);
}
- (void)restClient:(DBRestClient *)client loadProgress:(CGFloat)progress forFile:(NSString *)destPath
{
    NSLog(@"%f", progress);
}

Nel metodo restClient: loadedFile: la prima cosa che facciamo è creare un oggetto di tipo NSURL (che è la classe, nell'SDK Apple, utilizzata per la gestione degli URL a risorse sia locali sia web) utilizzando la stringa destPath. Allochiamo poi un oggetto di tipo NSURLRequest (ovvero la classe che consente di specificare oltre alla risorsa che vogliamo acquisire anche le ”regole” di acquisizione di tale risorsa) con l'NSURL creato. Infine carichiamo all'interno della _webView il contenuto della request precedentemente creata.

Come possiamo vedere, in questo caso abbiamo un terzo metodo di delegato: restClient: loadProgress: forFile:. Tale metodo ci consente di conoscere l'avanzamento del download per mezzo della variabile progess. Tale informazione è molto utile per far percepire all'utente il progresso dell'operazione per mezzo, ad esempio, di una UIProgressView, ovvero una barra che mostra, per esempio, l'avanzamento di un download.

Ultima operazione che dobbiamo implementare è la cancellazione della risorsa dalla cartella Documenti. Per far ciò sfruttiamo un metodo di delegato dell'oggetto UIWebView come segue:

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSFileManager *fileMgr = [NSFileManager defaultManager];
    NSError *error;
    [fileMgr removeItemAtPath:_filePath error:&error];
}

Concluso il lavoro sulla classe DocumentViewController dobbiamo adesso tornare nel file HierarchyViewController.h e dichiarare un bottone a cui associare la funzionalità di download di una risorsa:

UIButton *_downloadDocumentButton;

Allochiamo il bottone nel metodo di init fino a questo momento utilizzato nel file HierarchyViewController.m:

_downloadDocumentButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_downloadDocumentButton.frame = CGRectMake(10, 260, 300, 40);
[_downloadDocumentButton setTitle:@"Download documento" forState:UIControlStateNormal];
[_downloadDocumentButton addTarget:self action:@selector(didPressDownloadFile) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_downloadDocumentButton];

Dopo aver dichiarato il metodo didPressDownloadFile implementiamolo inserendo il
seguente codice che allocherà e mostrerà a schermo un oggetto di tipo DocumentViewController:

DocumentViewController * documentVC = [[DocumentViewController alloc]init];
documentVC.modalPresentationStyle = UIModalPresentationFullScreen;
documentVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:documentVC animated:YES];

Effettuando un Run del progetto e premendo il bottone Download File apparirà il nostro DocumentViewController (la classe che andrà a mostrare la risorsa scaricata); dopo qualche secondo comparirà anche la risorsa che abbiamo deciso di scaricare (il tempo necessario alla visualizzazione è ovviamente proporzionale alla dimensione della risorsa scaricata):

Figura 14. DocumentViewController dopo aver visualizzato una risorsa presente nella cartella Dropbox
(clic per ingrandire)


DocumentViewController dopo aver visualizzato una risorsa presente nella cartella Dropbox

Upload di un file

Per completare la gestione offline/online dei file, vediamo come eseguire l'upload di un file presente all'interno della nostra applicazione sui servizi online di Dropbox. Nulla vieta al lettore di estendere l'esempio che andremo a mostrare effettuando l'upload di un file, ad esempio, dal rullino fotografico.

Anche in questo caso dichiariamo un nuovo pulsante nel file HierarchyViewController.h:

UIButton *_uploadFileButton;

Dichiariamolo nel metodo di init nel file HierarchyViewController.m:

_uploadFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_uploadFileButton.frame = CGRectMake(10, 340, 300, 40);
[_uploadFileButton setTitle:@"Upload file" forState:UIControlStateNormal];
[_uploadFileButton addTarget:self action:@selector(didPressUploadFile) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_uploadFileButton];

Dopo aver dichiarato, con il codice sopra, il metodo didPressUploadFile inseriamo la sua implementazione (sempre nel file HierarchyViewController.m) come segue:

- (void)didPressUploadFile
{
    NSString *localPath = [[NSBundle mainBundle] pathForResource:@"logoHTML" ofType:@"jpg"];
    NSString *filename = @"logoHTML.jpg";
    NSString *destDir = @"/HTMLCloud";
    [_restClient uploadFile:filename toPath:destDir withParentRev:nil fromPath:localPath];
}

Come possiamo vedere, la prima cosa che facciamo è salvare il percorso locale relativo al file di cui vogliamo effettuare l'upload (localPath). Dopo aver definito il nome del file (filename) e il percorso in cui verrà copiato nella cartella condivisa Dropbox (destDir), richiamiamo il metodo uploadFile: toPath: withParentRev: fromPath:.

Adesso, come abbiamo fatto fino ad ora per ogni chiamata, aggiungiamo i metodi di delegato (sempre nel file HierarchyViewController.m):

- (void)restClient:(DBRestClient*)client uploadedFile:(NSString*)destPath from:(NSString*)srcPath metadata:(DBMetadata*)metadata {
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Upload file" message:@"Upload del file eseguito con successo" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"File uploaded successfully to path: %@", metadata.path);
}
- (void)restClient:(DBRestClient*)client uploadFileFailedWithError:(NSError*)error {
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Attenzione!" message:@"Impossibile effettuare l'upload del file" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    NSLog(@"File upload failed with error - %@", error);
}
- (void)restClient:(DBRestClient *)client uploadProgress:(CGFloat)progress forFile:(NSString *)destPath from:(NSString *)srcPath
{
    NSLog(@"Progress %f", progress);
}

Come possiamo vedere, anche in questo caso abbiamo a disposizione il metodo di delegato restClient: uploadProgress: forFile: from: che ci fornisce l'avanzamento dell'upload del file.

Ricerca di un file

Per completare tutte le potenzialità di un sistema del genere, vediamo ora l'ultima funzionalità che abbiamo previsto nel nostro progetto, ossia la possibilità di ricercare, una volta specificata un percorso, un file o una cartella.

CoCome sempre andiamo nel file HierarchyViewController.h e dichiariamo un nuovo bottone:

UIButton *_searchFolderOrFileButton;

Andiamo adesso nel metodo di init del file HierarchyViewController.m e dichiariamo il nuovo bottone:

_searchFolderOrFileButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_searchFolderOrFileButton.frame = CGRectMake(10, 410, 300, 40);
[_searchFolderOrFileButton setTitle:@"Cerca file" forState:UIControlStateNormal];
[_searchFolderOrFileButton addTarget:self action:@selector(didPressSearchFolderORFile) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_searchFolderOrFileButton];

Come sempre fatto fino ad ora, dichiariamo il metodo didPressSearchFolderORFile associato al tap del bottone ed inseriamone la sua implementazione:

- (void)didPressSearchFolderORFile{
	[_restClient searchPath:@"/HTMLCloud" forKeyword:@"HTML"];
}

Come possiamo vedere, anche in questo caso, è sufficiente una linea di codice per svolgere la funzione di ricerca. Il metodo searchPath: forKeyword: accetta in ingresso due parametri:

  • searchPath: rappresenta il percorso in cui verrà effettuata la ricerca. Ovviamente quest'ultima verrà estesa anche alle eventuali sottocartelle.
  • keyword: rappresenta la chiave di ricerca utilizzata. Sottolineiamo il fatto che la ricerca viene effettuata anche nell'estensione del file.

Inseriamo adesso i metodi di delegato:

- (void)restClient:(DBRestClient*)restClient loadedSearchResults:(NSArray *)results forPath:(NSString *)path keyword:(NSString *)keyword{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Ricerca" message:@"Ricerca terminata con successo" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
    for (DBMetadata * metadata in results) {
        NSLog(@"Nome file: %@", metadata.filename);
    }
}
- (void)restClient:(DBRestClient *)restClient searchFailedWithError:(NSError *)error{
    UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Attenzione!" message:@"Impossibile avviare la ricerca" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
    [av show];
}

Come possiamo vedere il metodo restClient: loadedSearchResults: forPath: keyword: oltre al percorso e alla keyword utilizzata per la ricerca, restituisce l'array result. Questo array contiene oggetti di tipo DBMetaData, gli stessi oggetti che abbiamo incontrato quando abbiamo implementato la funzionalità di acquisizione della lista di file o cartelle presenti in un determinato percorso.

Effettuando un Run del progetto e premendo il tasto Cerca file, sulla console otterremo un risultato simile al seguente:

Figura 15. Console con i risultati della ricerca
Screenshot relativo alla console che mostra i risultati della ricerca effettuata

Interfaccia utente avanzata

Durante l'evento HTML.it Release party 2012 è stata mostrata una demo di un'applicazione iOS che offre all'utente un'interfaccia grafica completa per poter interagire con i servizi di Dropbox. Le funzionalità dell'applicazione sono le stesse viste in questo articolo, ma con una grafica più gradevole.

La demo, pur essendo più complessa dal punto di vista del codice rispetto a quella mostrata in questo articolo (complessità dovuta dall'implementazione di un'interfaccia grafica più curata), possiede un numero esiguo di classi:

  • MenuViewController: offre le stesse funzionalità viste nell'articolo con un'interfaccia grafica minimale.
  • HierarchyViewController: offre tutte le funzionalità di interazione con i servizi di Dropbox che abbiamo analizzato passo passo fino a questo momento. Rispetto all'applicazione mostrata in questo articolo vengono mostrati a schermo sia i file e le cartelle ottenuti tramite la ricerca o tramite l'acquisizione dei DBMetadata appartenenti ad un percorso specifico. L'utente, semplicemente facendo tap sulle icone, potrà accedere ai contenuti della cartella oppure visualizzare un file. Effettuando invece un "long press" su un file o una cartella verrà mostrato una UIActionSheet (un componente di sistema che presenta all'utente una scelta multipla che possiamo trovare, per esempio, nell'applicazione Mail quando rispondiamo ad un messaggio) che consentirà la cancellazione di tale file o cartella.
  • DocumentViewController: mostra a schermo un file scaricato dalla cartella condivisa di Dropbox utilizzando la stessa metodologia vista in questo articolo.
  • NewFolderPopooverViewController: è un view controller che consente la creazione di una nuova cartella.

Il progetto demo presentato all'evento HTML.it Release party 2012 è liberamente scaricabile in allegato.

Ti consigliamo anche