Как связать типы файлов с приложением iPhone?

По вопросу об ассоциировании вашего iPhone-приложения с типами файлов.

В этом информационном вопросе я узнал, что приложения могут быть связаны с настраиваемыми URL-протоколами.

Это было почти год назад, и с тех пор Apple представила "Document Support", которая идет дальше и позволяет приложениям ассоциироваться с типами файлов. В documentation есть много разговоров о том, как настроить приложение для запуска других соответствующих приложений, когда он встречает неизвестный тип файла. Это означает, что ассоциация не работает из коробки для любого приложения, как это сделала регистрация протокола URL.

Это приводит меня к вопросу: имеют ли системные приложения, такие как Safari или Mail, эту систему для выбора связанных приложений или они ничего не делают, как раньше?

Ответ 1

Обработка типов файлов является новой с iPhone OS 3.2 и отличается от уже существующих схем пользовательских URL-адресов. Вы можете зарегистрировать свое приложение для обработки определенных типов документов, и любое приложение, использующее контроллер документа, может передать обработку этих документов в ваше собственное приложение.

Например, мое приложение Molecules (для которого доступен исходный код) обрабатывает типы файлов .pdb и .pdb.gz, если он получен по электронной почте или в другом поддерживаемом приложении.

Чтобы зарегистрировать поддержку, в вашем 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>

Предусмотрено два изображения, которые будут использоваться в качестве значков для поддерживаемых типов в Mail и других приложениях, способных отображать документы. Клавиша LSItemContentTypes позволяет вам предоставить массив унифицированных идентификаторов типов (UTI), которые может открыть ваше приложение. Список системных UTI см. В Apple Единый идентификатор идентификаторов типов. Более подробную информацию об UTI можно найти в Apple Единый обзор идентификаторов типов. Эти руководства находятся в центре разработчиков Mac, поскольку эта возможность была перенесена с Mac.

Один из UTI, используемых в приведенном выше примере, был системным, но другой был UTI приложения. UTI-приложения должны быть экспортированы, чтобы другие приложения в системе могли быть осведомлены об этом. Чтобы сделать это, вы добавили бы раздел в свой Info.plist следующим образом:

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

В этом конкретном примере экспортируется com.sunsetlakesoftware.molecules.pdb UTI с расширением файла .pdb, соответствующим типу MIME chemical/x-pdb.

При этом ваше приложение сможет обрабатывать документы, прикрепленные к электронным письмам или другим приложениям в системе. В Mail вы можете нажать и удерживать, чтобы открыть список приложений, которые могут открыть конкретное вложение.

Когда приложение будет открыто, ваше приложение будет запущено, и вам нужно будет обработать обработку этого файла в методе делегирования приложения -application:didFinishLaunchingWithOptions:. Похоже, что файлы, загруженные таким образом из Mail, копируются в ваш каталог документов Документов под подкаталогом, соответствующим тому, в каком почтовом ящике они прибыли. Вы можете получить URL-адрес этого файла в методе делегирования приложения, используя следующий код:

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

Обратите внимание, что это тот же подход, который мы использовали для обработки настраиваемых схем URL. Вы можете отделить URL-адреса файлов от других, используя следующий код:

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

Ответ 2

В дополнение к отличному ответу на Brad, я обнаружил, что (при iOS 4.2.1, по крайней мере) при открытии пользовательских файлов из приложения Mail ваше приложение не запускается или не уведомляется, если приложение было открыто ранее. Всплывающее окно "open with..." появляется, но просто ничего не делает.

Это, по-видимому, фиксируется (пере) перемещением файла из папки "Входящие". Безопасный подход, как представляется, заключается в том, чтобы оба (пере) перемещать файл по мере его открытия (в -(BOOL)application:openURL:sourceApplication:annotation:), а также через папку "Документы/Входящие", удаляя все элементы, например. в applicationDidBecomeActive:. Последний последний способ может понадобиться, чтобы вернуть приложение в чистое состояние, если предыдущий импорт вызывает сбой или прерывается.

Ответ 3

БОЛЬШОЕ ПРЕДУПРЕЖДЕНИЕ: сделайте ОДИН СТОЧНЫЙ ПРОЦЕНТ, чтобы ваше расширение еще не было привязано к типу mime.

Мы использовали расширение ".icz" для наших пользовательских файлов, в основном, когда-либо, и Safari просто никогда не позволял вам открывать их, говоря: "Safari не может открыть этот файл". независимо от того, что мы делали или пытались с использованием UT выше.

В конце концов я понял, что есть некоторые функции UT * C, которые вы можете использовать для изучения различных вещей, а while.icz дает правильный ответ (наше приложение):

В приложении действительно загрузилось сверху, просто сделайте это...

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

и положите разрыв после этой строки и посмотрите, что такое UTI и ur - в нашем случае это был наш идентификатор, как мы хотели), а url (ur) пакета указывал на нашу папку приложения.

Но тип MIME, который Dropbox возвращает нам для нашей ссылки, которую вы можете проверить, например,

$ 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

Контент-тип - это то, что мы хотим. Dropbox утверждает, что это текстовая/календарная запись. Отлично. Но в моем случае, я УЖЕ ТРЕНАЮЩИЙ ИЗОБРАЖЕНИЕ текст/календарь в мои mime-типы приложения, и он все еще не работает. Вместо этого, когда я пытаюсь получить UTI и связывать url для текстового/календарного mimetype,

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

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Я вижу "com.apple.ical.ics" как UTI и ".../MobileCoreTypes.bundle/" в качестве URL-адреса связки. Не наше приложение, а Apple. Поэтому я пытаюсь поместить com.apple.ical.ics в LSItemContentTypes вместе со своим собственным и в UTConformsTo в экспорт, но не уйти.

Итак, если Apple думает, что в какой-то момент они хотят обработать какую-то форму типа файла (которая может быть создана через 10 лет после того, как ваше приложение будет жить, заметьте), вам придется изменить расширение, потому что они просто не будут разрешите обрабатывать тип файла.

Ответ 4

Чтобы иметь дело с файлами любого типа для моего собственного приложения, я использую эту конфигурацию для 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>[email protected]</string>
            </array>
        </dict>
    </array>