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

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
  • 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

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

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)


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 Enable

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 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

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 Add

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 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

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 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 HTMLCloud-Info.plist

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 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

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:

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)


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 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:

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
  • HierarchyViewController DBMetadata UIActionSheet
  • DocumentViewController
  • NewFolderPopooverViewController

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

Ti consigliamo anche