Ciao a tutti, sono Francesco Noya, un nuovo autore di questa community di programmazione iPhone, e come primo articolo ho deciso di parlarvi di “estensioni di file”. A partire dalla versione 3.2 dell’SDK di Apple, infatti, è possibile registrare le estensioni di file che un’applicazione è in grado di gestire. Questo permette, ad esempio, di creare il proprio lettore di pdf da utilizzare quando si apre un allegato in Mail o con Safari. In questo tutorial vedremo come creare una piccola applicazione che apre automaticamente i file pdf e li mostra in una UIWebview.
Per prima cosa creiamo una “Window-based application” e diamole un nome (io l’ho chiamata “PDFFromSafari”).
A questo punto modifichiamo il file info.plist per registrare le estensioni che la nostra applicazione sarà in grado di manipolare. Per farlo impostiamo la visualizzazione del file come “Source Code File” in modo da vedere la sua struttura come file xml.

Il file aperto si presenta più o meno così:

Andiamo ad aggiungere le seguenti righe:
UIApplicationExitsOnSuspend
CFBundleDocumentTypes
CFBundleTypeIconFiles
CFBundleTypeName
NSPasteboardTypePDF
CFBundleTypeRole
Viewer
LSHandlerRank
Alternate
LSItemContentTypes
com.adobe.pdf
Analizziamo quello che abbiamo scritto:
UIApplicationExitsOnSuspend
Questa opzione impone all’applicazione di chiudersi quando si preme il pulsante dell’iPhone anziché entrare in Background. Ovviamente questo si applica solo se il dispositivo su cui lavoriamo è al iOS 4, altrimenti questo è il comportamento standard.
Le righe successive invece riguardano proprio la registrazione delle estensioni gestite dall’applicazione.
In particolare:
CFBundleTypeIconFiles
Contiene un array di stringhe contenenti il percorso all’icona che viene associata al file nel menù contestuale dei programmi che lo possono aprire.
CFBundleTypeName
Ha una stringa con il nome del tipo di documento che apre (nel nostro esempio “NSPasteboardTypePDF”).
LSHandlerRank
Raprresenta il ruolo che ha l’applicazione. Nel nostro caso con Alternate specifichiamo che si tratta di un modo alternativo per aprire il file
Infine:
LSItemContentTypes
contiene un Array di Uniform Type Identifiers (UTIs) che l’applicazione è in grado d’aprire. Nel nostro esempio i PDF: com.adobe.pdf
Ora che abbiamo modificato il file info.plist salviamolo e andiamo a scrivere il codice dell’ applicazione. In particolar modo quello che facciamo è cambiare il metodo
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Dell’Application Delegate.
Ecco le modifiche da fare:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSURL *urlFileEsterno = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
if(urlFileEsterno != NULL){
//carico il pdf in un oggetto NSData
NSData *pdf = [[NSData alloc] initWithContentsOfURL:urlFileEsterno];
UIWebView *webview = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
[webview loadData:pdf MIMEType:@"application/pdf" textEncodingName:nil baseURL:nil];
[pdf release];
webview.scalesPageToFit = YES;
[window addSubview:webview];
[webview release];
//elimino il file copiato sul dispositivo
NSFileManager *filemanager = [NSFileManager defaultManager];
[filemanager removeItemAtURL:urlFileEsterno error:NULL];
[filemanager release];
}else {
//mostro un alert
UIAlertView *popUp = [[UIAlertView alloc] initWithTitle:@"Aprimi da Safari"
message:@"Prova ad aprirmi da Safari o dal programma Mail"
delegate:self
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[popUp show];
[popUp release];
}
[window makeKeyAndVisible];
return YES;
}
Vediamo di capire cosa fa:
NSURL *urlFileEsterno = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
Questo è l’URL del file esterno. Ogni volta che un file viene aperto questi viene memorizzato all’interno della sottocartella inbox dei Documents dell’applicazione.
if(urlFileEsterno != NULL){
Controllo l’esistenza del file. Se il file esiste allora lo salvo all’interno di un oggetto NSData grazie al metodo:
NSData *pdf = [[NSData alloc] initWithContentsOfURL:urlFileEsterno];
Questo permette di aprire il file in una UIWebView con il metodo
[webview loadData:pdf MIMEType:@"application/pdf" textEncodingName:nil baseURL:nil];
Per finire istanziamo un oggetto NSFileManager che si occupa di eliminare il file creato (Ovviamente nulla ci vieta di tenerlo):
NSFileManager *filemanager = [NSFileManager defaultManager];
[filemanager removeItemAtURL:urlFileEsterno error:NULL];
[filemanager release];
(NB. Il metodo removeItemAtURL è stato introdotto dalla SDK 4, per cui se state usando versioni precedenti dovrete usare qualche accorgimento e cambiare il metodo con removeItemAtPath).
Quello che fa il blocco dell’else è semplicemente visualizzare un alert quando si apre l’applicazione in maniera “normale”, senza passare da Safari (o chi per esso).
Salviamo ed eseguiamo… dal momento che il simulatore non ha Mail, ho testato il funzionamento dell’app aprendo Gmail da Safari ed andando ad aprire una mail con allegato un pdf.
Vediamo il risultato:
se avvio l’applicazione:

Quando apro il pdf in Safari compare il menu Apri in:

Lo stesso pdf aperto nella nostra applicazione:

Considerazioni Finali
Ciò che rende molto potente il meccanismo delle UTI è che permette di definire anche tipi di file proprietari. Se siete interessati ad un esempio che include la definizione di UTI personali vi rimando a questa discussione su StackOverflow (in Inglese) al seguente indirizzo.
Per avere invece maggiori informazioni, invece, sulla definizione dei CFBundleDocumentTypes questi sono alcuni link alla documentazione Apple:









10 Responses to “T#065 – Registrare le estensioni di file supportate da un Applicazione iPhone”
22 Luglio 2010
Noyapare che wordpress si mangi tutti i tag di apertura dell’xml! 🙂
22 Luglio 2010
Antonio GiarrussoNon ho capito perché il file plist non poteva essere modificato direttamente da Xcode premendo il tasto + e aggiungendo la stringa 🙂
22 Luglio 2010
Tweets that mention Registrare le estensioni di file supportate da un Applicazione iPhone | devAPP -- Topsy.com[…] This post was mentioned on Twitter by iPadWorld.it, devAPP. devAPP said: T#065 – Registrare le estensioni di file supportate da un Applicazione iPhone http://bit.ly/cUjGc3 […]
22 Luglio 2010
ba7suGrande, ma stavi al De Sanctis?
23 Luglio 2010
NoyaOvviamente si può fare anche alla tua maniera… ma se qualcuno è pigro 🙂 e vuol farsi un bel copia-incolla, questo è il modo più veloce 😉
23 Luglio 2010
VinceSiete al solito grandiii…
Scusate avrei un problema con un mio progettino…
Nella mia app ho usato un UISegmentedControl a 4 segmenti per far cambiare il testo di una label alla pressione di ogni segmento.
Come posso fare per salvare il segmento premuto usando NSUserdefaults e all’avvio mostrare il testo corrispondente nella label?
Ecco la funzione:
-(void)cambiaOperatore:(id)sender {
if (segmentedControl.selectedSegmentIndex == 0) {
[operatore setText:@”Tim”];
}
if (segmentedControl.selectedSegmentIndex == 1) {
[operatore setText:@”Tre”];
}
if (segmentedControl.selectedSegmentIndex == 2) {
[operatore setText:@”Vodafone”];
}
if (segmentedControl.selectedSegmentIndex == 3) {
[operatore setText:@”Wind”];
}
}
26 Luglio 2010
PaoloMa è possibile cambiare anche safari come browser di default e rendere una nostra applicazione l’applicazione la seguente?
27 Luglio 2010
NoyaiPhone è un sistema molto chiuso, per cui non è possibile cambiare il browser di default… a meno di avere un cellulare col jailbreak.
11 Dicembre 2010
Emiliociao grazie mille per la guida è proprio quello che stavo cercando.nella mia app vorrei eseguire una cosa molto simile solamente che invece di un pdf vorrei aprire un file xml (public.xml -giusta uti?) e vorrei che i dati che vengano caricati da questo xml siano “parsati” in 3 textfield..il parser che ho carica i file da un xml locale e li parsa alla perfezione..come potrei fare con un file proveniente da una mail??grazie a tutti:D G.
16 Giugno 2011
Lucae’ possibile passare l’indirizzo di una cartella di un server dove vado a mettere un database sqlite e poi gestire i dati??