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

318

На предмет связи вашего приложения iPhone с типами файлов.

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

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

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

Михай Дамиан
источник

Ответы:

408

Обработка типов файлов впервые появилась в 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>

Предоставляются два изображения, которые будут использоваться в качестве значков для поддерживаемых типов в Почте и других приложениях, способных отображать документы. LSItemContentTypesКлюч позволяет обеспечить ряд единообразных типа идентификаторов (ИМП) , что ваше приложение может открыть. Список системных 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.pdbUTI с расширением файла .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
}
Брэд Ларсон
источник
9
Следует отметить, что -application:didFinishLaunchingWithOptions:в приложении делегат вызывается только в том случае, если ваше приложение не было фоновым, когда оно открыто для обработки файла.
меммон
3
Как избежать QuickLook: raywenderlich.com/1980/…
TheLearner
4
Мы должны использовать - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urlтакже на iOS 4+
Дмитрий
1
Как насчет ключа 'CFBundleTypeExtensions'? Ваш фрагмент, кажется, не устанавливает его. Разве это не обязательно?
Брэм
3
Я испробовал всю методологию, представленную здесь и в других местах, но я все еще пытаюсь получить открытые файлы PNG. Я работаю с iOS 7. В некоторых местах говорят, что эта проблема начинается с ios 6. Это правда? Разве мы не можем открыть png файлы в диалоговом окне «Открыть в» с ios 7?
Кумар Адитья
24

В дополнение к отличному ответу Брэда, я обнаружил, что (по крайней мере на iOS 4.2.1) при открытии пользовательских файлов из приложения «Почта» ваше приложение не запускается и не уведомляется, если вложение было открыто ранее. Появляется всплывающее окно «открыть с помощью…», но ничего не происходит.

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

MVDS
источник
6
Я не вижу такого поведения. Если мое приложение имеет фон, -(BOOL)application:openURL:sourceApplication:annotation:всегда вызывается, даже для вложений, которые уже были открыты. Каждый раз, когда вложение открывается, к имени файла добавляется суффикс, который увеличивается до уникального - test.text, test-1.txt, test-2.txt и т. Д.
memmons 10.10.11
Моя папка «Входящие» пуста, но у меня есть не отвечающая кнопка «Открыть в» в Safari, о которой вы говорите. Несколько лет назад мое приложение работало нормально, но вдруг оно перестало работать. Я подозреваю, что Apple изменила что-то в Safari.
Брэм
18

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

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

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

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

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

и поместите break после этой строки и посмотрите, что такое 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

Content-Type - это то, что мы хотим. Dropbox утверждает, что это текстовая / календарная запись. Отлично. Но в моем случае я уже пробовал помещать текст / календарь в типы пантомимы моего приложения, и он все еще не работает. Вместо этого, когда я пытаюсь получить UTI и пакетный URL для типа mimetype text / calendar,

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 лет после того, как ваше приложение будет работать, учтите), вам придется изменить расширение, потому что они просто не позволят вам обрабатывать тип файла.

Kalle
источник
Спасибо за полезное предупреждение!
RockSolid
0

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