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
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:
Si aprirà una pop-up come quella rappresentata nella figura sotto:
Tutti i campi mostrati nel form di registrazione sono obbligatori:
- App name
- Description
- Access Level
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
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
Andando oltre possiamo vedere che sono presenti altri due campi (AppKey AppSecret
Additional users
Figura 04. Sezione Additional users relativa alla pagina di un'applicazione Dropbox
(clic per ingrandire)
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 Enable

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:
Scegliamo come nome HTMLCloud Device Family iPhone Automatic Reference Count
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 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 Security.framework HTMLCloud Target Build phases
Esploriamo dunque la sezione Link Binary With Libraries Add

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
import
#import <DropboxSDK/DropboxSDK.h>
#define APPKEY @"2sjagz8grla0nyi"
#define APPSECRET @"xx7e1fmvq6g8t28"
I valori relativi ad APPKEY
APPSECRET
Adesso spostiamoci nel metodo application: didFinishLaunchingWithOptions:
frame
window
DBSession* dbSession = [[DBSession alloc] initWithAppKey:APPKEY appSecret:APPSECRET root:kDBRootDropbox];
[DBSession setSharedSession:dbSession];
La classe DBSession
APPKEY
APPSECRET
Abbandoniamo adesso il file AppDelegate.m Empty Application AppDelegate UIViewController subclass MenuViewController
Spostiamoci poi nel file MenuViewController.h
UIButton *_linkButton;
UIButton *_enterButton;
A questo punto spostiamoci nel file MenuViewController.m
#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
Da notare, nell'ultima riga di codice, l'accesso alla property
isLinked
DBSession
property
YES
NO
Nel codice indicato sopra abbiamo inoltre associato al bottone _linkButton
didPressLink
_enterButton
showDropboxFolder
Per dichiararli, sempre nel file MenuViewController.m
@implementation MenuViewController
@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
didPressLink
Prima di tutto, per differenziare l'operazione di login da quella di logout, utilizziamo la property
isLinked
DBSession
linkFromController:
unlinkAll
A questo punto la scrittura del MenuViewController
updateButtonsLabelWithState:
_linkButton
MenuViewController.h
- (void)updateButtonsLabelWithState:(BOOL)linked;
Spostiamoci poi nel metodo MenuViewController.m
- (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
AppDelegate.h
MenuViewController
Per prima cosa, importiamo il file MenuViewController.h
MenuViewController
MenuViewController *_menuVC;
Spostiamoci nel file AppDelegate.m
application:didFinishLaunchingWithOptions:
DBSession
MenuViewController * menuVC = [[MenuViewController alloc] init];
self.window.rootViewController = menuVC;
Ultima modifica da apportare al file AppDelegate.m
- (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
Open As
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:
Se tocchiamo il pulsante Accedi con account Dropbox HTMLCloud-Info.plist
Tocchiamo dunque il tasto Allow
HTMLCloud-Info.plist
Figura 12. Schermata di menu quando è stato eseguito il Login
(clic per ingrandire)
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
init
- (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
@implementation HierarchyViewController
@interface HierarchyViewController(private)
- (void)didPressShowFiles;
@end
@implementation HierarchyViewController(private)
- (void)didPressShowFiles{
}
@end
Arrivati a questo punto dovremmo implementare il metodo didPressShowFiles
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
DBRestClient *_restClient;
A questo punto spostiamoci nel file HierarchyViewController.m
init
_showFilesListButton
_showFilesListButton:
- (id)init {
_restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
_restClient.delegate = self;
}
Come possiamo vedere allochiamo l'oggetto _restClient
DBSession
self
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
isDirectory
contents
DBMetadata
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
HierarchyViewController *hierarchyVC = [[HierarchyViewController alloc] init];
[self presentModalViewController:hierarchyVC animated:YES];
A questo punto eseguiamo un Run Lista Files HTMLCloud

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:
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
- Visualizzazione del file all'interno di una
UIWebView
- Cancellazione della risorsa dalla cartella Documenti
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
- (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
UIToolbar
UIBarButtonItem
Documenti
_filePath
loadFile: intoPath:
dropboxPath
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:
NSURL
destPath
NSURLRequest
NSURL
_webView
request
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
HierarchyViewController.h
UIButton *_downloadDocumentButton;
Allochiamo il bottone nel metodo di init
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
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)
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
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
HierarchyViewController.m
- (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
filename
destDir
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
HierarchyViewController.m
_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
- (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:
searchPath
keyword
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:
result
DBMetaData
Effettuando un Run del progetto e premendo il tasto Cerca file, sulla console otterremo un risultato simile al seguente:

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
HierarchyViewController
DBMetadata
UIActionSheet
DocumentViewController
NewFolderPopooverViewController
Il progetto demo presentato all'evento HTML.it Release party 2012 è liberamente scaricabile in allegato.