关于将iPhone应用程序与文件类型关联的主题。
在这信息问题,我了解到应用程序可以与自定义URL协议相关联。
大约一年前,苹果推出了“文档支持”,允许应用程序与文件类型关联。在文档中有很多关于如何设置你的应用在遇到未知文件类型时启动其他适当的应用的讨论。这意味着关联不会像URL协议注册那样,对任何应用程序开箱即用。
这就引出了一个问题:像Safari或Mail这样的系统应用程序是否实现了这个选择相关应用程序的系统,还是像以前一样什么都不做?
文件类型处理是iPhone OS 3.2的新特性,与现有的自定义URL方案不同。您可以注册您的应用程序来处理特定的文档类型,任何使用文档控制器的应用程序都可以将这些文档的处理转交给您自己的应用程序。
例如,我的应用程序分子(其源代码可用)处理.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移植过来了。
LSItemContentTypes
上面示例中使用的一个UTI是系统定义的,但另一个是特定于应用程序的UTI。需要导出特定于应用程序的UTI,以便系统上的其他应用程序可以知道它。要做到这一点,您需要在Info中添加一个部分。请像下面这样写:
<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。
com.sunsetlakesoftware.molecules.pdb
chemical/x-pdb
有了这些,您的应用程序将能够处理附加到电子邮件或系统上其他应用程序的文档。在Mail中,您可以长按打开一个可以打开特定附件的应用程序列表。
当打开附件时,您的应用程序将被启动,您将需要在-application:didFinishLaunchingWithOptions:应用程序委托方法中处理此文件的处理。以这种方式从Mail加载的文件似乎被复制到应用程序的Documents目录下的子目录中,该子目录与它们到达的电子邮箱对应。您可以在应用程序委托方法中使用如下代码获取该文件的URL:
-application:didFinishLaunchingWithOptions:
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
注意,这与我们处理自定义URL方案时使用的方法相同。您可以使用如下代码将文件url与其他url分开:
if ([url isFileURL]) { // Handle file being passed in } else { // Handle custom URL scheme }
除了Brad的精彩回答之外,我还发现(至少在iOS 4.2.1上)当从邮件应用程序打开自定义文件时,如果附件之前已被打开,应用程序不会被触发或通知。“用…打开”弹出框出现,但什么也不做。
这似乎可以通过(重新)从收件箱目录移动文件来解决。一个安全的方法似乎是在文件打开时(在-(BOOL)application:openURL:sourceApplication:annotation:中)(重新)移动文件,同时遍历Documents/Inbox目录,删除所有项,例如在applicationDidBecomeActive:中。为了防止之前的导入导致崩溃或中断,可能需要使用最后的catch-all使应用程序再次处于干净状态。
-(BOOL)application:openURL:sourceApplication:annotation:
applicationDidBecomeActive:
大警告:请百分之百确定您的扩展没有绑定到某个mime类型。
我们使用了扩展名'。icz'用于我们的自定义文件,基本上,永远,Safari不会让你打开它们说"Safari无法打开这个文件"不管我们用上面的UT做了什么或尝试了什么。
最终,我意识到有一些UT* C函数可以用来探索各种东西,而.icz给出了正确的答案(我们的应用程序):
在app did load at top中,只需要这样做…
NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)@"icz", NULL); CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);
在这行后面加上break,看看UTI和ur是什么——在我们的例子中,它是我们想要的标识符),bundle 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”。作为UTI和…/MobileCoreTypes. ics。bundle/"作为bundle URL。不是我们的应用,而是苹果。所以我试着把com.apple.ical.ics和我自己的放在LSItemContentTypes中,并在导出中放入UTConformsTo,但没有成功。
所以基本上,如果苹果认为他们想要在某个时候处理某种形式的文件类型(注意,这可能是在你的应用程序发布10年后创建的),你将不得不改变扩展名,因为他们不会让你处理文件类型。
为了处理我自己的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>
安装duti。它是立即将uti绑定到Appls的最完整和最严肃的解决方案。你有它在这里:duti在GitHub上
如果你喜欢图形界面:SwiftDefaultApps在GitHub上