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

Mih*_*ian 318 cocoa-touch ios

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

这个提供信息的问题中,我了解到应用程序可能与自定义URL协议相关联.

那是差不多一年前,从那时起,Apple推出了"文档支持",它更进一步,允许应用程序与文件类型相关联.文档中有很多关于如何设置应用程序以在遇到未知文件类型时启动其他适当应用程序的讨论.这意味着关联对于任何应用程序都不能开箱即用,就像URL协议注册那样.

这引出了一个问题:让像Safari或Mail这样的系统应用程序实现这个系统来选择相关的应用程序,还是像以前一样什么也不做?

Bra*_*son 403

文件类型处理是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>
Run Code Online (Sandbox Code Playgroud)

提供了两个图像,这些图像将用作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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
Run Code Online (Sandbox Code Playgroud)

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

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}
Run Code Online (Sandbox Code Playgroud)

  • 应该注意的是,只有当你的应用程序在打开处理文件时没有后台处理时,才会调用app委托中的`-application:didFinishLaunchingWithOptions:`. (9认同)
  • 我们应该在iOS 4+上使用` - (BOOL)应用程序:(UIApplication*)应用程序handleOpenURL:(NSURL*)url` (4认同)
  • 避免使用QuickLook:http://www.raywenderlich.com/1980/how-to-import-and-export-app-data-via-email-in-your-ios-app (3认同)
  • 我已经尝试了这里提供的所有方法以及其他地方,但我仍然在努力获取打开的PNG文件.我正在使用iOS 7.在某些地方,他们说这个问题始于ios 6.这是真的吗?我们不能在ios 7的"打开方式"对话框中打开png文件吗? (3认同)

mvd*_*vds 24

除了Brad的出色答案之外,我还发现(至少在iOS 4.2.1上)从Mail应用程序打开自定义文件时,如果之前已经打开了附件,则不会触发或通知您的应用程序.出现"打开..."弹出窗口,但什么也没做.

这似乎是通过(重新)从Inbox目录移动文件来解决的.一个安全的方法似乎是(重新)移动文件,因为它打开(in -(BOOL)application:openURL:sourceApplication:annotation:)以及通过Documents/Inbox目录,删除所有项目,例如applicationDidBecomeActive:.如果先前的导入导致崩溃或被中断,则可能需要最后一次全部捕获以使应用程序再次处于干净状态.

  • 我没有看到这种行为.如果我的应用程序是后台的,` - (BOOL)应用程序:openURL:sourceApplication:annotation:`总是被调用,即使对于已经打开的附件也是如此.打开附件的每个额外时间,数字后缀为文件名,并增加为唯一 - test.text,test-1.txt,test-2.txt等. (6认同)

Kal*_*lle 18

大警告:确保你的扩展程序没有绑定某些mime类型.

对于我们的自定义文件,我们使用了扩展名".icz",基本上,只是,Safari永远不会让你打开它们说"Safari无法打开这个文件".无论我们用上面的UT做过什么或尝试过什么.

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

在应用程序确实加载在顶部,只是这样做...

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                                                                   (CFStringRef)@"icz", 
                                                                   NULL);
CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);
Run Code Online (Sandbox Code Playgroud)

并在该行之后放置并查看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
Run Code Online (Sandbox Code Playgroud)

Content-Type就是我们想要的.Dropbox声称这是一个文本/日历条目.大.但在我的情况下,我已经将文本/日历转换成我的应用程序的mime类型,但它仍然无法正常工作.相反,当我尝试获取文本/日历mimetype的UTI和捆绑网址时,

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

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);
Run Code Online (Sandbox Code Playgroud)

我将"com.apple.ical.ics"视为UTI,将".../MobileCoreTypes.bundle /"视为捆绑URL.不是我们的应用程序,而是Apple.所以我尝试将com.apple.ical.ics放在我自己的LSItemContentTypes中,然后放到导出中的UTConformsTo中,但是没有去.

所以基本上,如果Apple认为他们想要在某种程度上处理某种形式的文件类型(可能是在你的应用程序上线10年后创建的,请注意),你将不得不改变扩展名,因为他们根本不会让你处理文件类型.