UIDocumentInteractionController,没有文件扩展名,但 UTI
如何将文件发送到不同的应用程序并了解该应用程序支持哪种 UTI?假设该文件没有文件扩展名,但我碰巧知道该文件的 UTI。
我尝试了以下操作:
// target is a NSURL with the location of the extension less file on the system
// knownUTI is a NSString containing the UTI of the file
UIDocumentInteractionController* dic = [UIDocumentInteractionController interactionControllerWithURL:target];
[dic retain];
dic.delegate = self;
dic.UTI = knownUTI;
[dic presentOpenInMenuFromRect:CGRectZero inView:superController.view animated:YES]
它显示了支持的应用程序,但是,如果我选择它,它不会切换应用程序。委托调用
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application
但从
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
未被调用,并且应用程序永远不会切换。
目标应用程序导出其 UTI 如下:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Migration DocType</string>
<key>CFBundleTypeRol</key>
<string>Shell</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.mycomp.customstring</string>
</array>
</dict>
</array>
...
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>My custom UTI</string>
<key>UTTypeIdentifier</key>
<string>com.mycomp.customstring</string>
</dict>
</array>
由于这不起作用,我还尝试添加自定义扩展。不过,这样是行不通的。将自定义扩展添加到文件时,我将其移交给 DocumentInteractionController
并且它可以工作。但是,应用程序列表显示所有其他应用程序都支持相同的文件扩展名,无论 UTI I 型电源如何。
假设我在 2 个不同的应用程序中声明 2 个 UTI:
App1 with UTI1: com.mycomp.a with extension .abc
App2 with UTI2: com.mycomp.b with extension .abc
将文件传递给 DocumentInteractionController 并将 UTI 设置为 com.mycomp.a 时,它还会将 App2 显示为能够处理该文件的可能应用程序。
我通过以下方式定义了带有扩展名的 UTI:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>My UTI Type</string>
<key>UTTypeIdentifier</key>
<string>com.mycomp.a</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>abc</string>
<key>public.mime-type</key>
<string>application/abc</string>
</dict>
</dict>
</array>
我非常感谢您的帮助,我有点卡住了。 那么,问题又来了:如何将文件发送到具有已知 UTI 的应用程序,或者没有扩展名,或者与我不想在 DocumentInteractionController 中显示应用程序的其他文件具有相同的扩展名?
谢谢
How do I send a file to a different App knowing which UTI the App supports? Lets say the file has no file extension, but I happen to know the UTI of the file.
I tried the following:
// target is a NSURL with the location of the extension less file on the system
// knownUTI is a NSString containing the UTI of the file
UIDocumentInteractionController* dic = [UIDocumentInteractionController interactionControllerWithURL:target];
[dic retain];
dic.delegate = self;
dic.UTI = knownUTI;
[dic presentOpenInMenuFromRect:CGRectZero inView:superController.view animated:YES]
It shows the supported App, however, if I select it, it won't switch the App. The delegate calls the
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application
but
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
is never called and the Application is never switching.
The target App exports its UTI in the following:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Migration DocType</string>
<key>CFBundleTypeRol</key>
<string>Shell</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.mycomp.customstring</string>
</array>
</dict>
</array>
...
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>My custom UTI</string>
<key>UTTypeIdentifier</key>
<string>com.mycomp.customstring</string>
</dict>
</array>
As this did not work, I also tried adding a custom extension. Still, it would not work in this way. When adding the custom extension to the file I hand over to the DocumentInteractionController
and it works. However, the list of applications shows all other applications supporting the same file extension regardless of the UTI type I supply.
Say I declare 2 UTIs in 2 different applications:
App1 with UTI1: com.mycomp.a with extension .abc
App2 with UTI2: com.mycomp.b with extension .abc
When handing the file to the DocumentInteractionController, and setting the UTI to com.mycomp.a
it will also show App2 as a possible application being able to handle the file.
I defined a UTI with extension in the following manner:
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string>
</array>
<key>UTTypeDescription</key>
<string>My UTI Type</string>
<key>UTTypeIdentifier</key>
<string>com.mycomp.a</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<string>abc</string>
<key>public.mime-type</key>
<string>application/abc</string>
</dict>
</dict>
</array>
I would really appreciate your help, I'm kind of stuck.
So, again the question: How do I send a file to an App with known UTI either without extension or having the same extension as other files of which I don't want to show the applications as choice in DocumentInteractionController?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我找到了解决这个问题的方法。不过,我认为这并不是一件很好的事情。
在测试过程中,我发现当保留文件扩展名时,
UIDocumentInteractionController
将根据我指定的UTI
显示应用程序。将文件发送到目标应用程序时不会发生任何事情。我的结论是我需要一个文件扩展名来完成最终的发送。我的方法是在将文件发送到目标应用程序之前修改
URL
属性,并向其提供相同的文件,但具有目标应用程序接受的文件扩展名。尽管如此,我的应用程序还是崩溃了。我使用 Instruments 对其进行了分析,发现问题是由于UIDocumentInteractionController
过度释放了某些代理对象。我还看到最终的过度释放是在
UIDocumentInteractionController(Private)
类别的名为_invalidate
的方法中调用的,该方法释放了对象。由于类别不能被其他类别覆盖,我决定用我自己的实现来混合类别方法,检查 URL 是否包含文件扩展名,然后将调用重定向到原始
_invalidate
方法,或者只是执行没有什么。以下代码显示了我所做的操作:
此代码将原始
_invalidate
方法与_invalidateMY
交换,导致每次调用_invalidate
时都会调用_invalidateMY
反之亦然。以下代码显示了我如何处理
UIDocumentInteractionController
:此代码显示了
UIDocumentInteractionController
的交换 URL 的委托方法:此解决方案有效,但在我看来,它是一个肮脏的黑客,必须有更好的解决方案。
I found a solution to this problem. However, I think it is not a very good one.
During testing I found out that when leaving the file extension away, the
UIDocumentInteractionController
will show the applications depending on theUTI
I specified. When sending the file to the target application nothing would happen. I concluded that I need an file extension to do the final sending.My approach was to modify the
URL
property before the file is sent to the target application and supply it the same file but with a file extension the target application accepts. Nevertheless, my application just crashed. I profiled it with Instruments and found that the problem was due toUIDocumentInteractionController
overreleasing some proxy object.I also saw that the final overrelease was in a method called
_invalidate
ofUIDocumentInteractionController(Private)
category was called which released the object.As categories cannot be overridden by other categories I decided to swizzle the category method with my own implementation checking if the URL was containing a file extension or not and either redirect the call to the original
_invalidate
method or just do nothing.The following codes shows what I did:
This code exchanges the original
_invalidate
method with_invalidateMY
, resulting in every call to_invalidate
calling_invalidateMY
and vice versa.The following code shows how I handle the
UIDocumentInteractionController
:And this code shows the
UIDocumentInteractionController
's delegate method which exchanges the URL:This solution works, but in my opinion it is a dirty hack, there must be a better solution.