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
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
UIDocumentInteractionControllerwill show the applications depending on theUTII 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
URLproperty 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 toUIDocumentInteractionControlleroverreleasing some proxy object.I also saw that the final overrelease was in a method called
_invalidateofUIDocumentInteractionController(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
_invalidatemethod or just do nothing.The following codes shows what I did:
This code exchanges the original
_invalidatemethod with_invalidateMY, resulting in every call to_invalidatecalling_invalidateMYand 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.