Wie ordne ich Dateitypen einer iPhone-Anwendung zu?

318

Zum Thema Verknüpfen Ihrer iPhone-App mit Dateitypen.

In dieser informativen Frage habe ich gelernt, dass Apps mit benutzerdefinierten URL-Protokollen verknüpft werden können.

Das war vor fast einem Jahr und seitdem hat Apple den "Document Support" eingeführt, der einen Schritt weiter geht und es Apps ermöglicht, Dateitypen zuzuordnen. In der Dokumentation wird viel darüber gesprochen, wie Sie Ihre App so einrichten, dass andere geeignete Apps gestartet werden, wenn ein unbekannter Dateityp auftritt. Dies bedeutet, dass die Zuordnung für keine App sofort funktioniert, wie dies bei der Registrierung des URL-Protokolls der Fall war.

Dies führt mich zu der Frage: Haben System-Apps wie Safari oder Mail dieses System für die Auswahl der zugehörigen Anwendungen implementiert oder tun sie nach wie vor nichts?

Mihai Damian
quelle

Antworten:

408

Die Behandlung von Dateitypen ist neu in iPhone OS 3.2 und unterscheidet sich von den bereits vorhandenen benutzerdefinierten URL-Schemata. Sie können Ihre Anwendung registrieren, um bestimmte Dokumenttypen zu verarbeiten, und jede Anwendung, die einen Dokumentencontroller verwendet, kann die Verarbeitung dieser Dokumente an Ihre eigene Anwendung übergeben.

Beispielsweise verarbeitet meine Anwendung Molecules (für die der Quellcode verfügbar ist) die Dateitypen .pdb und .pdb.gz, wenn sie per E-Mail oder in einer anderen unterstützten Anwendung empfangen werden.

Um den Support zu registrieren, müssen Sie Folgendes in Ihrer Info.plist haben:

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

Es werden zwei Bilder bereitgestellt, die als Symbole für die unterstützten Typen in Mail und anderen Anwendungen verwendet werden, die Dokumente anzeigen können. Mit dem LSItemContentTypesSchlüssel können Sie ein Array von UTIs (Uniform Type Identifiers) bereitstellen, die Ihre Anwendung öffnen kann. Eine Liste der systemdefinierten UTIs finden Sie in der Apple Uniform Type Identifiers Reference . Weitere Informationen zu HWI finden Sie in der Übersicht über die einheitlichen Typkennungen von Apple . Diese Handbücher befinden sich im Mac Developer Center, da diese Funktion gegenüber dem Mac portiert wurde.

Eine der im obigen Beispiel verwendeten UTIs war systemdefiniert, die andere war eine anwendungsspezifische UTI. Die anwendungsspezifische UTI muss exportiert werden, damit andere Anwendungen auf dem System darauf aufmerksam gemacht werden können. Dazu fügen Sie Ihrer Info.plist einen Abschnitt wie den folgenden hinzu:

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

In diesem Beispiel wird die com.sunsetlakesoftware.molecules.pdbUTI mit der Dateierweiterung .pdb exportiert, die dem MIME-Typ entspricht chemical/x-pdb.

Mit dieser Funktion kann Ihre Anwendung Dokumente verarbeiten, die an E-Mails oder von anderen Anwendungen im System angehängt sind. In Mail können Sie durch Tippen und Halten eine Liste von Anwendungen aufrufen, mit denen ein bestimmter Anhang geöffnet werden kann.

Wenn der Anhang geöffnet wird, wird Ihre Anwendung gestartet und Sie müssen die Verarbeitung dieser Datei in Ihrer -application:didFinishLaunchingWithOptions:Anwendungsdelegatmethode durchführen. Es scheint, dass auf diese Weise aus Mail geladene Dateien in das Dokumentenverzeichnis Ihrer Anwendung unter einem Unterverzeichnis kopiert werden, das dem E-Mail-Feld entspricht, in dem sie angekommen sind. Sie können die URL für diese Datei innerhalb der Anwendungsdelegatmethode mithilfe des folgenden Codes abrufen:

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

Beachten Sie, dass dies der gleiche Ansatz ist, den wir für die Behandlung von benutzerdefinierten URL-Schemata verwendet haben. Sie können die Datei-URLs von anderen trennen, indem Sie folgenden Code verwenden:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Brad Larson
quelle
9
Es ist zu beachten, dass -application:didFinishLaunchingWithOptions:der Delegat in der App nur aufgerufen wird, wenn Ihre App beim Öffnen zur Verarbeitung einer Datei nicht im Hintergrund war.
Memmons
3
Vermeiden von QuickLook
TheLearner
4
Wir sollten - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urlauch auf iOS 4+
Dmitry
1
Was ist mit dem Schlüssel 'CFBundleTypeExtensions'? Ihr Snippet scheint es nicht zu setzen. Ist es nicht erforderlich?
Bram
3
Ich habe alle hier und an anderen Stellen bereitgestellten Methoden ausprobiert, aber ich habe immer noch Probleme, offene PNG-Dateien zu erhalten. Ich arbeite mit iOS 7. An einigen Stellen wird gesagt, dass dieses Problem mit iOS 6 beginnt. Stimmt es? Können wir mit ios 7 keine PNG-Dateien im Dialogfeld "Öffnen in" öffnen?
Kumar Aditya
24

Zusätzlich zu Brads hervorragender Antwort habe ich herausgefunden, dass (zumindest unter iOS 4.2.1) beim Öffnen benutzerdefinierter Dateien über die Mail-App Ihre App nicht ausgelöst oder benachrichtigt wird, wenn der Anhang zuvor geöffnet wurde. Das Popup "Öffnen mit ..." wird angezeigt, tut aber nichts.

Dies scheint behoben zu sein, indem die Datei aus dem Posteingangsverzeichnis (erneut) verschoben wird. Ein sicherer Ansatz scheint darin zu bestehen, die Datei beim Öffnen (in -(BOOL)application:openURL:sourceApplication:annotation:) (neu) zu verschieben sowie das Verzeichnis "Dokumente / Posteingang" zu durchsuchen und alle Elemente zu entfernen, z applicationDidBecomeActive:. B. in . Dieser letzte Haken kann erforderlich sein, um die App wieder in einen sauberen Zustand zu versetzen, falls ein vorheriger Import einen Absturz verursacht oder unterbrochen wird.

mvds
quelle
6
Ich sehe dieses Verhalten nicht. Wenn meine App im Hintergrund ist, -(BOOL)application:openURL:sourceApplication:annotation:wird sie immer aufgerufen, auch für Anhänge, die bereits geöffnet wurden. Jedes weitere Mal, wenn der Anhang geöffnet wird, wird eine Nummer an den Dateinamen angehängt und inkrementiert, um eindeutig zu sein - test.text, test-1.txt, test-2.txt usw.
memmons
Mein Posteingangsverzeichnis ist leer, aber ich habe die nicht reagierende Schaltfläche "Öffnen in" in Safari, von der Sie sprechen. Vor Jahren funktionierte meine App einwandfrei, aber plötzlich funktionierte sie nicht mehr. Ich vermute, Apple hat in Safari etwas geändert.
Bram
18

GROSSE WARNUNG: Stellen Sie EINHUNDERT PROZENT sicher, dass Ihre Erweiterung nicht bereits an einen MIME-Typ gebunden ist.

Wir haben die Erweiterung '.icz' für unsere benutzerdefinierten Dateien im Grunde genommen immer verwendet, und Safari lässt Sie sie niemals öffnen, wenn Sie sagen: "Safari kann diese Datei nicht öffnen." egal was wir mit dem obigen UT-Zeug gemacht oder versucht haben.

Irgendwann wurde mir klar, dass es einige UT * C-Funktionen gibt, mit denen Sie verschiedene Dinge erkunden können, und während .icz die richtige Antwort gibt (unsere App):

In der App wurde oben geladen, mach das einfach ...

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

und setzen Sie nach dieser Zeile eine Pause und sehen Sie, was UTI und ur sind - in unserem Fall war es unsere Kennung, wie wir wollten), und die Bundle-URL (ur) zeigte auf den Ordner unserer App.

Aber der MIME-Typ, den Dropbox uns für unseren Link zurückgibt, den Sie überprüfen können, indem Sie z

$ 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

Der Inhaltstyp ist das, was wir wollen. Dropbox behauptet, dies sei ein Text- / Kalendereintrag. Großartig. Aber in meinem Fall habe ich BEREITS VERSUCHT, Text / Kalender in die MIME-Typen meiner App einzufügen, und es funktioniert immer noch nicht. Wenn ich stattdessen versuche, die UTI zu erhalten und die URL für den Text- / Kalender-Mimetyp zu bündeln,

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

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Ich sehe "com.apple.ical.ics" als UTI und "... / MobileCoreTypes.bundle /" als Bundle-URL. Nicht unsere App, sondern Apple. Also versuche ich, com.apple.ical.ics neben meinen eigenen in die LSItemContentTypes und im Export in UTConformsTo einzufügen, aber es geht nicht.

Wenn Apple glaubt, irgendwann einen Dateityp verarbeiten zu wollen (der 10 Jahre nach dem Start Ihrer App erstellt werden könnte, wohlgemerkt), müssen Sie die Erweiterung ändern, da Sie einfach nicht damit umgehen können der Dateityp.

Kalle
quelle
Danke für die nützliche Warnung!
RockSolid
0

Um mit beliebigen Dateitypen für meine eigene APP umzugehen, verwende ich diese Konfiguration für 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>
SLdragon
quelle