Search code examples
iosinfo.plistios-sharesheetcfbundledocumenttypes

How can I get my app to show up in any "Open In..." sheet on iOS?


I have an iOS app with in-app features that let the user select photos from their albums or take photos with the camera. I'd like to also allow users to import photos that they find anywhere else on their phone: Mail, Safari, Photos...any app that lets users long-press an image and see the "Share..." menu.

I've been wrestling with this for about two weeks. I believe I'm following the documentation perfectly, but so far, the only place I can get my app to appear is when a user is sharing exactly one photo from the Photos app. It doesn't show up if multiple images are selected in Photos, nor does it show up for images in Safari or Mail.

Now, I know this is possible, because dozens of other third-party apps appear in the Share sheet for any of those kinds of images (on my device: Instagram, OmniFocus, Instapaper, Obsidian, ChatGPT, to name just a few).

And these are not Share Sheet extensions either - almost all of these will open the destination app in full and switch the focus away from the source app.

The main primary source I have to go on is this Apple TechNote ("How do I get my application to show up in the Open in... menu."). I started a fresh Xcode project, made the changes suggested in this document and....just as with my actual app, the only place I see this icon is for single photos in the Photos.app.

I've tried different permutations of LSHandlerRank, and CFBundleTypeRole; I've tried with and without CFBundleTypeIconFiles; with and without LSSupportsOpeningDocumentsInPlace; I've gone from general UTI's like public.data and public.content to intermediate ones like public.image and specific ones like public.jpeg. None works for me. I tried opening a code-level case with Apple Developer Support, but am still awaiting an answer. (I'm using these catch-all UTI's because other applications that have this working seem to appear in every Share sheet, everywhere on the device_

I did see my app icon appear one time in the Share sheet, but when I tried again, it didn't happen. It seems like my CFBundleDocumentTypes get cached by the operating system and unpredictably refreshed. I wasn't able to get back to the state that caused it.

What on earth am I doing wrong here? I've included very simple instructions on what I'm doing with a fresh project and would appreciate any concrete advice anyone can give me.

Below are the steps I followed to get my non-working CFBundleDocumentTypes config from a fresh Xcode project. Note that I've already tried lots of different combinations, so please don't just suggest random new combinations for me to try - what I'd like to hear is a config that actually works, since it seems to be trivial for all of these other apps to implement.

  1. Create a new Xcode project.
  2. Add the following to Info.plist:
    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>Image</string>
            <key>LSHandlerRank</key>
            <string>Owner</string>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.data</string>
                <string>public.content</string>
                <string>public.item</string>
            </array>
        </dict>
    </array>
  <key>LSSupportsOpeningDocumentsInPlace</key>
   <true/>
  1. Though I don't think this should affect iOS's ability to find the bundle's document types, add this to your auto-generated SceneDelegate for good measure:
  func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    for context in URLContexts {
      let url = context.url
      if let data = try? Data(contentsOf: url),
         let image = UIImage(data: data) {
        
        let alert = UIAlertController()
        alert.title = "Loaded an image"
        alert.message = "Size is \(image.size)"
        
        window?.rootViewController?.present(alert, animated: true, completion: nil)
      }
    }
  }

NOTES: You can try with or without LSSupportsOpeningDocumentsInPlace - it hasn't made a difference for me.


Solution

  • You say "long press" but that's not actually correct: the user needs to tap the image. This works fine for me, to make my app show up in the list when the user taps an image file in a Mail message or a Messages message (as well as a single image in Photos) and then asks to Share it:

    <key>CFBundleTypeName</key>
    <string>Image</string>
    <key>LSHandlerRank</key>
    <string>Default</string>
    <key>LSItemContentTypes</key>
    <array>
        <string>public.image</string>
    </array>
    

    I don't know of an app where this can be done with multiple images in Photos; apps that appear in the Share sheet when there is a multiple selection in Photos are using a Share Extension. You can't select and share multiple image files in a Mail message, so the issue of multiples doesn't arise.