Come associo i tipi di file a un'applicazione iPhone?


318

Per quanto riguarda l'associazione della tua app per iPhone a tipi di file.

In questa domanda informativa ho appreso che le app potevano essere associate a protocolli URL personalizzati.

Questo è successo quasi un anno fa e da allora Apple ha introdotto "Document Support", che fa un ulteriore passo avanti e consente alle app di associarsi ai tipi di file. Si parla molto nella documentazione su come configurare l'app per avviare altre app appropriate quando incontra un tipo di file sconosciuto. Ciò significa che l'associazione non funziona immediatamente per nessuna app, come ha fatto la registrazione del protocollo URL.

Questo mi porta alla domanda: le app di sistema come Safari o Mail hanno implementato questo sistema per scegliere le applicazioni associate o non faranno nulla, come prima?

Risposte:


408

La gestione dei tipi di file è nuova con iPhone OS 3.2 ed è diversa dagli schemi URL personalizzati già esistenti. È possibile registrare l'applicazione per gestire determinati tipi di documenti e qualsiasi applicazione che utilizza un controller di documenti può trasferire l'elaborazione di questi documenti alla propria applicazione.

Ad esempio, la mia applicazione Molecules (per la quale è disponibile il codice sorgente) gestisce i tipi di file .pdb e .pdb.gz, se ricevuti via e-mail o in un'altra applicazione supportata.

Per registrare il supporto, devi avere qualcosa di simile al seguente nel tuo Info.plist:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array>
            <string>Document-molecules-320.png</string>
            <string>Document-molecules-64.png</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>Molecules Structure File</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.sunsetlakesoftware.molecules.pdb</string>
            <string>org.gnu.gnu-zip-archive</string>
        </array>
    </dict>
</array>

Vengono fornite due immagini che verranno utilizzate come icone per i tipi supportati in Mail e altre applicazioni in grado di mostrare documenti. La LSItemContentTypeschiave consente di fornire un array di identificatori di tipo uniforme (UTI) che l'applicazione può aprire. Per un elenco di UTI definite dal sistema, consulta il riferimento agli identificatori di tipo uniforme di Apple . Ulteriori dettagli sugli UTI sono disponibili nella panoramica degli identificatori di tipo uniforme di Apple . Queste guide risiedono nel centro per sviluppatori Mac, poiché questa funzionalità è stata trasferita dal Mac.

Uno degli UTI utilizzati nell'esempio sopra era definito dal sistema, ma l'altro era un UTI specifico dell'applicazione. L'ITU specifica dell'applicazione dovrà essere esportata in modo che altre applicazioni sul sistema possano essere rese consapevoli di esso. Per fare ciò, aggiungi una sezione al tuo Info.plist come la seguente:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pdb</string>
            <key>public.mime-type</key>
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>

Questo esempio particolare esporta l' com.sunsetlakesoftware.molecules.pdbITI con l'estensione del file .pdb, corrispondente al tipo MIME chemical/x-pdb.

Con questo in atto, l'applicazione sarà in grado di gestire i documenti allegati alle e-mail o da altre applicazioni sul sistema. In Mail, puoi toccare e tenere premuto per visualizzare un elenco di applicazioni in grado di aprire un particolare allegato.

Quando l'allegato viene aperto, l'applicazione verrà avviata e sarà necessario gestire l'elaborazione di questo file nel -application:didFinishLaunchingWithOptions:metodo delegato dell'applicazione. Sembra che i file caricati in questo modo da Mail vengano copiati nella directory Documenti dell'applicazione in una sottodirectory corrispondente alla casella di posta elettronica in cui sono arrivati. È possibile ottenere l'URL per questo file all'interno del metodo delegato dell'applicazione usando il codice seguente:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];

Si noti che questo è lo stesso approccio che abbiamo usato per gestire schemi URL personalizzati. Puoi separare gli URL dei file dagli altri usando il codice come il seguente:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}

9
Va notato che -application:didFinishLaunchingWithOptions:nell'app delegato viene chiamato solo se l'app non era in background quando è aperta per gestire un file.
Memmons

3
Evitando QuickLook: raywenderlich.com/1980/…
TheLearner

4
Dovremmo usare - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urlanche su iOS 4+
Dmitry il

1
Che dire della chiave "CFBundleTypeExtensions"? Il tuo frammento non sembra impostarlo. Non è richiesto?
Bram,

3
Ho provato tutta la metodologia fornita qui e anche in altri luoghi, ma sto ancora lottando per ottenere file PNG aperti. Sto lavorando con iOS 7. In alcuni punti stanno dicendo che questo problema inizia con iOS 6. È vero? Non possiamo aprire i file png nella finestra di dialogo "Apri in" con iOS 7?
Kumar Aditya,

24

Oltre all'ottima risposta di Brad, ho scoperto che (almeno su iOS 4.2.1) quando si aprono file personalizzati dall'app Mail, l'app non viene attivata o notificata se l'allegato è stato aperto in precedenza. Viene visualizzato il popup "Apri con ...", ma non fa nulla.

Ciò sembra essere risolto spostando (ri) il file dalla cartella Posta in arrivo. Un approccio sicuro sembra essere sia quello di (ri) spostare il file quando viene aperto (in -(BOOL)application:openURL:sourceApplication:annotation:) sia di passare attraverso la directory Documents / Inbox, rimuovendo tutti gli elementi, ad esempio in applicationDidBecomeActive:. L'ultimo catch-all potrebbe essere necessario per riportare l'app in uno stato pulito, nel caso in cui un'importazione precedente causi un arresto anomalo o venga interrotta.


6
Non vedo questo comportamento. Se la mia app è in background, -(BOOL)application:openURL:sourceApplication:annotation:viene sempre chiamata, anche per gli allegati che sono già stati aperti. Ogni volta che si apre l'allegato, un numero viene aggiunto al nome del file e viene incrementato per essere univoco - test.text, test-1.txt, test-2.txt, ecc.
Memmons

La mia cartella Posta in arrivo è vuota, ma ho il pulsante "Apri in" che non risponde in Safari di cui parli. Anni fa, la mia app funzionava bene, ma all'improvviso ha smesso di funzionare. Sospetto che Apple abbia cambiato qualcosa in Safari.
Bram,

18

GRANDE AVVERTENZA: assicurati che UN CENTRO PER CENTO sia sicuro che la tua estensione non sia già legata a un tipo MIME.

Abbiamo usato l'estensione '.icz' per i nostri file personalizzati per, praticamente, in assoluto, e Safari non ti avrebbe mai lasciato aprire dicendo "Safari non può aprire questo file". non importa cosa abbiamo fatto o provato con le cose UT sopra.

Alla fine mi sono reso conto che ci sono alcune funzioni UT * C che puoi usare per esplorare varie cose, e mentre .icz dà la risposta giusta (la nostra app):

Nell'app è stato caricato in alto, basta fare questo ...

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                                                                   (CFStringRef)@"icz", 
                                                                   NULL);
CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

e interrompi dopo quella linea e vedi cosa sono UTI e ur - nel nostro caso, era il nostro identificatore come volevamo) e l'URL bundle (ur) puntava alla cartella della nostra app.

Ma il tipo MIME che Dropbox ci restituisce per il nostro link, che puoi controllare facendo ad es

$ curl -D headers THEURLGOESHERE > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27393  100 27393    0     0  24983      0  0:00:01  0:00:01 --:--:-- 28926
$ cat headers
HTTP/1.1 200 OK
accept-ranges: bytes
cache-control: max-age=0
content-disposition: attachment; filename="123.icz"
Content-Type: text/calendar
Date: Fri, 24 May 2013 17:41:28 GMT
etag: 872926d
pragma: public
Server: nginx
x-dropbox-request-id: 13bd327248d90fde
X-RequestId: bf9adc56934eff0bfb68a01d526eba1f
x-server-response-time: 379
Content-Length: 27393
Connection: keep-alive

Il tipo di contenuto è ciò che vogliamo. Dropbox afferma che si tratta di una voce di testo / calendario. Grande. Ma nel mio caso, ho già provato a mettere il testo / calendario nei tipi mime della mia app, e ancora non funziona. Invece, quando provo a ottenere l'URI e l'URL del bundle per il mimetype text / calendar,

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
                                                                   (CFStringRef)@"text/calendar", 
                                                                   NULL);

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Vedo "com.apple.ical.ics" come UTI e "... / MobileCoreTypes.bundle /" come URL del bundle. Non la nostra app, ma Apple. Quindi provo a inserire com.apple.ical.ics in LSItemContentTypes insieme al mio, e in UTConformsTo nell'esportazione, ma non ci riesco.

Quindi in pratica, se Apple pensa che a un certo punto vorranno gestire una qualche forma di tipo di file (che potrebbe essere creato 10 anni dopo che l'app è attiva, intendiamoci), dovrai cambiare l'estensione perché semplicemente non ti lasceranno gestire il tipo di file.


Grazie per l'avviso utile!
RockSolid,

0

Per gestire qualsiasi tipo di file per la mia APP, utilizzo questa configurazione per CFBundleDocumentTypes:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>IPA</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.item</string>
                <string>public.content</string>
                <string>public.data</string>
                <string>public.database</string>
                <string>public.composite-content</string>
                <string>public.contact</string>
                <string>public.archive</string>
                <string>public.url-name</string>
                <string>public.text</string>
                <string>public.plain-text</string>
                <string>public.source-code</string>
                <string>public.executable</string>
                <string>public.script</string>
                <string>public.shell-script</string>
                <string>public.xml</string>
                <string>public.symlink</string>
                <string>org.gnu.gnu-zip-archve</string>
                <string>org.gnu.gnu-tar-archive</string>
                <string>public.image</string>
                <string>public.movie</string>
                <string>public.audiovisual-​content</string>
                <string>public.audio</string>
                <string>public.directory</string>
                <string>public.folder</string>
                <string>com.apple.bundle</string>
                <string>com.apple.package</string>
                <string>com.apple.plugin</string>
                <string>com.apple.application-​bundle</string>
                <string>com.pkware.zip-archive</string>
                <string>public.filename-extension</string>
                <string>public.mime-type</string>
                <string>com.apple.ostype</string>
                <string>com.apple.nspboard-typ</string>
                <string>com.adobe.pdf</string>
                <string>com.adobe.postscript</string>
                <string>com.adobe.encapsulated-​postscript</string>
                <string>com.adobe.photoshop-​image</string>
                <string>com.adobe.illustrator.ai-​image</string>
                <string>com.compuserve.gif</string>
                <string>com.microsoft.word.doc</string>
                <string>com.microsoft.excel.xls</string>
                <string>com.microsoft.powerpoint.​ppt</string>
                <string>com.microsoft.waveform-​audio</string>
                <string>com.microsoft.advanced-​systems-format</string>
                <string>com.microsoft.advanced-​stream-redirector</string>
                <string>com.microsoft.windows-​media-wmv</string>
                <string>com.microsoft.windows-​media-wmp</string>
                <string>com.microsoft.windows-​media-wma</string>
                <string>com.apple.keynote.key</string>
                <string>com.apple.keynote.kth</string>
                <string>com.truevision.tga-image</string>
            </array>
            <key>CFBundleTypeIconFiles</key>
            <array>
                <string>Icon-76@2x</string>
            </array>
        </dict>
    </array>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.