如何将文件类型与 iPhone 应用程序相关联?

Posted

技术标签:

【中文标题】如何将文件类型与 iPhone 应用程序相关联?【英文标题】:How do I associate file types with an iPhone application? 【发布时间】:2010-05-05 14:59:22 【问题描述】:

关于将您的 iPhone 应用程序与文件类型相关联的主题。

在this 信息性问题中,我了解到应用程序可以与自定义 URL 协议相关联。

那是差不多一年前的事了,从那时起,Apple 推出了“文档支持”,它更进了一步,允许应用与文件类型相关联。 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>

提供了两个图像,它们将用作邮件和其他能够显示文档的应用程序中支持的类型的图标。 LSItemContentTypes 键允许您提供应用程序可以打开的统一类型标识符 (UTI) 数组。有关系统定义的 UTI 列表,请参阅 Apple 的 Uniform Type Identifiers Reference。有关 UTI 的更多详细信息,请参阅 Apple 的 Uniform Type Identifiers Overview。这些指南位于 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>

此特定示例导出带有 .pdb 文件扩展名的 com.sunsetlakesoftware.molecules.pdb UTI,对应于 MIME 类型 chemical/x-pdb

有了这个,您的应用程序将能够处理附加到电子邮件或系统上其他应用程序的文档。在 Mail 中,您可以点击并按住以调出可以打开特定附件的应用程序列表。

打开附件后,您的应用程序将启动,您需要在-application:didFinishLaunchingWithOptions: 应用程序委托方法中处理此文件。看起来,以这种方式从 Mail 加载的文件被复制到应用程序的 Documents 目录中,该目录下的子目录与它们到达的邮箱相对应。您可以使用如下代码在应用程序委托方法中获取此文件的 URL:

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

请注意,这与我们用于处理自定义 URL 方案的方法相同。您可以使用如下代码将文件 URL 与其他 URL 分开:

if ([url isFileURL])

    // Handle file being passed in

else

    // Handle custom URL scheme

【讨论】:

需要注意的是,应用代理中的-application:didFinishLaunchingWithOptions:只有在你的应用在打开处理文件时没有后台时才会被调用。 避免快速查看:raywenderlich.com/1980/… 我们应该在 ios 4+ 上也使用- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url “CFBundleTypeExtensions”键呢?你的 sn-p 似乎没有设置它。不需要吗? 我已经尝试了这里和其他地方提供的所有方法,但我仍然在努力获取打开的 PNG 文件。我正在使用 iOS 7。在某些地方,他们说这个问题始于 ios 6。是真的吗?我们不能在 iOS 7 的“打开方式”对话框中打开 png 文件吗?【参考方案2】:

除了 Brad 的出色回答之外,我发现(至少在 iOS 4.2.1 上)从 Mail 应用程序打开自定义文件时,如果之前打开过附件,您的应用程序不会被触发或通知。 “打开方式...”弹出窗口出现,但什么也不做。

这似乎可以通过从收件箱目录中(重新)移动文件来解决。一种安全的方法似乎是在打开文件时(在-(BOOL)application:openURL:sourceApplication:annotation: 中)同时(重新)移动文件,以及通过 Documents/Inbox 目录,删除所有项目,例如在applicationDidBecomeActive:。如果之前的导入导致崩溃或被中断,则可能需要最后的全部内容才能使应用再次处于干净状态。

【讨论】:

我没有看到这种行为。如果我的应用程序是后台的,则始终调用-(BOOL)application:openURL:sourceApplication:annotation:,即使对于已经打开的附件也是如此。每次打开附件时,文件名后面都会加上一个数字,并递增为唯一——test.text、test-1.txt、test-2.txt 等。 我的收件箱目录是空的,但是你所说的 Safari 中的“打开”按钮没有响应。几年前,我的应用程序运行良好,但突然停止运行。我怀疑苹果在 Safari 中改变了一些东西。【参考方案3】:

重大警告:确保 100% 的扩展程序尚未绑定到某些 mime 类型。

我们为自定义文件使用了扩展名“.icz”,基本上,Safari 永远不会让您打开它们说“Safari 无法打开此文件”。无论我们对上面的 UT 内容做了什么或尝试了什么。

最终我意识到有一些 UT* C 函数可以用来探索各种事物,而 .icz 给出了正确的答案(我们的应用程序):

在应用中确实在顶部加载,只需执行此操作...

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

然后在该行后面加上 break ,看看 UTI 和 ur 是什么——在我们的例子中,它是我们想要的标识符),并且包 url (ur) 指向我们应用程序的文件夹。

但是 Dropbox 为我们的链接返回给我们的 MIME 类型,您可以通过例如检查

$ 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 声称这是一个文本/日历条目。伟大的。但就我而言,我已经尝试将文本/日历放入我的应用程序的 mime 类型中,但它仍然不起作用。相反,当我尝试获取文本/日历 mimetype 的 UTI 和捆绑 URL 时,

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

为了处理我自己的APP的任何类型的文件,我对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>

【讨论】:

TIFF 文件的“LSItemContentTypes”可能是什么?你能帮忙吗!

以上是关于如何将文件类型与 iPhone 应用程序相关联?的主要内容,如果未能解决你的问题,请参考以下文章

将 vcard 的文件类型与 iPhone 应用程序相关联

将文件类型与我的 Iphone 应用程序关联

如何使用 .desktop 文件(在 linux 下)将文件扩展名与应用程序相关联?

将文件类型与 Chrome 打包应用程序相关联

如何将单选按钮值与输入字段相关联

如何将程序与文件类型关联,但仅适用于当前用户?