Jak powiązać typy plików z aplikacją na iPhone'a?

318

Na temat powiązania aplikacji iPhone z typami plików.

W tym pytaniu informacyjnym dowiedziałem się, że aplikacje mogą być powiązane z niestandardowymi protokołami adresów URL.

To było prawie rok temu i od tego czasu Apple wprowadził „obsługę dokumentów”, która idzie o krok dalej i pozwala aplikacjom na kojarzenie z typami plików. Istnieje wiele rozmów w dokumentacji o tym, jak skonfigurować aplikację, aby uruchomić inne odpowiednie aplikacje, gdy napotka nieznany typ pliku. Oznacza to, że powiązanie nie działa od razu po wyjęciu z pudełka jakiejkolwiek aplikacji, podobnie jak rejestracja protokołu URL.

To prowadzi mnie do pytania: czy aplikacje systemowe, takie jak Safari lub Mail, zaimplementowały ten system do wybierania powiązanych aplikacji, czy też nie zrobią nic, jak wcześniej?

Mihai Damian
źródło

Odpowiedzi:

408

Obsługa typów plików jest nowa w iPhone OS 3.2 i różni się od już istniejących niestandardowych schematów adresów URL. Możesz zarejestrować swoją aplikację, aby obsługiwać określone typy dokumentów, a każda aplikacja korzystająca z kontrolera dokumentów może przekazać przetwarzanie tych dokumentów własnej aplikacji.

Na przykład moja aplikacja Molekuły (dla których dostępny jest kod źródłowy) obsługuje typy plików .pdb i .pdb.gz, jeśli otrzymano je pocztą elektroniczną lub w innej obsługiwanej aplikacji.

Aby zarejestrować wsparcie, musisz mieć coś takiego w swoim 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>

Dostępne są dwa obrazy, które będą używane jako ikony obsługiwanych typów w programie Mail i innych aplikacjach, które mogą wyświetlać dokumenty. Ten LSItemContentTypesklucz pozwala podać tablicę identyfikatorów jednolitych typów (UTI), które aplikacja może otworzyć. Aby zapoznać się z listą zdefiniowanych przez system interfejsów użytkownika, zobacz dokument Apple Uniform Type Identifier Reference . Jeszcze więcej szczegółów na temat UTI można znaleźć w Omówieniu jednolitych identyfikatorów typów Apple . Przewodniki te znajdują się w centrum deweloperów komputerów Mac, ponieważ ta funkcja została przeniesiona z komputera Mac.

Jeden z UTI zastosowanych w powyższym przykładzie został zdefiniowany przez system, ale drugi był ZTI specyficzny dla aplikacji. Interfejs użytkownika specyficzny dla aplikacji będzie musiał zostać wyeksportowany, aby inne aplikacje w systemie mogły o nim wiedzieć. Aby to zrobić, dodaj sekcję do swojej Info.plist w następujący sposób:

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

Ten konkretny przykład eksportuje com.sunsetlakesoftware.molecules.pdbinterfejs użytkownika z rozszerzeniem .pdb, odpowiadającym typowi MIME chemical/x-pdb.

Dzięki temu aplikacja będzie mogła obsługiwać dokumenty załączone do wiadomości e-mail lub innych aplikacji w systemie. W aplikacji Mail możesz dotknąć i przytrzymać, aby wyświetlić listę aplikacji, które mogą otworzyć określony załącznik.

Po otwarciu załącznika aplikacja zostanie uruchomiona i będziesz musiał obsłużyć przetwarzanie tego pliku w -application:didFinishLaunchingWithOptions:metodzie delegowania aplikacji. Wygląda na to, że pliki załadowane w ten sposób z Maila są kopiowane do katalogu dokumentów aplikacji w podkatalogu odpowiadającym, do której skrzynki e-mailowej dotarły. Możesz uzyskać adres URL tego pliku w ramach metody delegowania aplikacji, używając kodu takiego jak poniżej:

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

Pamiętaj, że to samo podejście zastosowaliśmy do obsługi niestandardowych schematów adresów URL. Możesz oddzielić adresy URL plików od innych przy użyciu kodu takiego jak poniżej:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Brad Larson
źródło
9
Należy zauważyć, że -application:didFinishLaunchingWithOptions:w aplikacji delegat jest wywoływany tylko wtedy, gdy aplikacja nie była uruchomiona w tle, gdy jest otwarta do obsługi pliku.
memmons,
3
Unikanie QuickLook: raywenderlich.com/1980/…
TheLearner
4
Powinniśmy używać - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urlrównież na iOS 4+
Dmitry
1
Co z kluczem „CFBundleTypeExtensions”? Twój fragment wydaje się go nie ustawiać. Czy to nie jest wymagane?
Bram
3
Wypróbowałem całą metodologię podaną tutaj, a także w innych miejscach, ale wciąż staram się uzyskać otwarte pliki PNG. Pracuję z iOS 7. W niektórych miejscach mówią, że ten problem zaczyna się od iOS 6. Czy to prawda? Czy nie można otworzyć plików png w oknie dialogowym „Otwórz w” w systemie iOS 7?
Kumar Aditya
24

Oprócz doskonałej odpowiedzi Brada dowiedziałem się, że (przynajmniej na iOS 4.2.1) podczas otwierania niestandardowych plików z aplikacji Poczta aplikacja nie jest uruchamiana ani powiadamiana, jeśli załącznik był wcześniej otwierany. Pojawi się wyskakujące okno „otwórz za pomocą ...”, ale nic nie robi.

Wydaje się, że jest to naprawione przez (ponowne) przeniesienie pliku z katalogu skrzynki odbiorczej. Bezpiecznym podejściem wydaje się być zarówno (ponowne) przeniesienie pliku podczas jego otwierania ( -(BOOL)application:openURL:sourceApplication:annotation:wewnątrz), jak i przeglądanie katalogu Dokumenty / Skrzynka odbiorcza, usuwanie wszystkich elementów, np applicationDidBecomeActive:. W. Ten ostatni catch-all może być potrzebny do ponownego uruchomienia aplikacji w przypadku, gdy poprzedni import spowoduje awarię lub zostanie przerwany.

mvds
źródło
6
Nie widzę tego zachowania. Jeśli moja aplikacja działa w tle, -(BOOL)application:openURL:sourceApplication:annotation:jest zawsze wywoływana, nawet w przypadku załączników, które zostały już otwarte. Za każdym razem, gdy załącznik jest otwierany, do nazwy pliku jest dodawany przyrostek i jest on zwiększany tak, aby był unikalny - test.text, test-1.txt, test-2.txt itp.
memmons
Mój katalog skrzynki odbiorczej jest pusty, ale mam nieodpowiadający przycisk „Otwórz w” w przeglądarce Safari, o której mówisz. Wiele lat temu moja aplikacja działała dobrze, ale nagle przestała działać. Podejrzewam, że Apple zmieniło coś w Safari.
Bram
18

WIELKIE OSTRZEŻENIE: Upewnij się, że JEDEN STOŻEK PROCENTOWY ma pewność, że twoje rozszerzenie nie jest już powiązane z jakimś typem MIME.

Użyliśmy rozszerzenia „.icz” dla naszych niestandardowych plików, w zasadzie na zawsze, a Safari po prostu nigdy nie pozwoli ci ich otworzyć, mówiąc: „Safari nie może otworzyć tego pliku”. bez względu na to, co zrobiliśmy lub wypróbowaliśmy z materiałami UT powyżej.

W końcu zdałem sobie sprawę, że istnieją pewne funkcje UT * C, których można używać do eksploracji różnych rzeczy, a podczas gdy .icz daje właściwą odpowiedź (nasza aplikacja):

W aplikacji ładowałem na górze, po prostu zrób to ...

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

i położyć kres po tej linii i zobaczyć, jakie są UTI i ur - w naszym przypadku był to nasz identyfikator, jak chcieliśmy), a adres URL pakietu (ur) wskazywał na folder naszej aplikacji.

Ale typ MIME, który Dropbox zwraca nam dla naszego linku, który możesz sprawdzić, wykonując np

$ 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

Typ zawartości jest tym, czego chcemy. Dropbox twierdzi, że jest to wpis tekstowy / kalendarzowy. Świetny. Ale w moim przypadku JUŻ SPRÓBOWAŁEM WSTAWIANIE tekstu / kalendarza do typów MIME mojej aplikacji i nadal nie działa. Zamiast tego, gdy próbuję uzyskać identyfikator UTI i pakiet URL dla typu tekstowego / kalendarza,

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

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Widzę „com.apple.ical.ics” jako UTI i „... / MobileCoreTypes.bundle /” jako adres URL pakietu. Nie nasza aplikacja, ale Apple. Próbuję więc umieścić com.apple.ical.ics w LSItemContentTypes obok moich własnych i w UTConformsTo w eksporcie, ale nie ma mowy.

Zasadniczo, jeśli Apple myśli, że w pewnym momencie chce obsłużyć jakiś typ pliku (który może zostać utworzony 10 lat po uruchomieniu aplikacji, pamiętaj), musisz zmienić rozszerzenie, ponieważ po prostu nie pozwoli ci to obsłużyć typ pliku.

Kalle
źródło
Dzięki za przydatne ostrzeżenie!
RockSolid 16.04.16
0

Aby poradzić sobie z dowolnym rodzajem plików dla mojej własnej aplikacji, używam tej konfiguracji dla 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
źródło