You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让iOS应用在各类「打开方式…」及分享菜单中正常显示?

iOS应用全局分享菜单适配问题

问题背景

我开发的iOS应用支持相册选图和相机拍照,现在需要实现:用户能从Mail、Safari、Photos等所有支持长按图片调出「分享…」菜单的应用中,通过分享直接导入图片到我的应用。

目前仅在Photos应用分享单张图片时能看到我的应用,多选图片、Safari或Mail中的图片分享时均不显示。已知Instagram、OmniFocus等第三方应用可以实现该功能,且它们并非使用分享扩展,而是直接打开目标应用。

已尝试的操作

  • 严格按照Apple技术笔记QA1587配置新Xcode项目,结果与实际应用一致,仅Photos单图场景有效
  • 尝试过LSHandlerRank、CFBundleTypeRole的各种组合
  • 测试过有无CFBundleTypeIconFiles、LSSupportsOpeningDocumentsInPlace的情况
  • 覆盖了从public.data这类通用UTI到public.image、public.jpeg这类特定UTI的所有配置
  • 已提交Apple开发者技术支持工单,暂未收到回复
  • 曾偶然出现应用图标在分享菜单中,但无法复现,推测是系统缓存CFBundleDocumentTypes导致刷新不稳定

现有配置步骤

  1. 创建新Xcode项目
  2. 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. SceneDelegate中添加代码:
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)
        }
    }
}

注:有无LSSupportsOpeningDocumentsInPlace对结果无影响

可行配置方案

1. 修正Info.plist的UTI配置

需要明确指定图片类UTI,同时添加LSFileQuarantineEnabled并设置为false,确保系统不会因为安全隔离过滤掉应用。更新后的CFBundleDocumentTypes配置如下:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeName</key>
        <string>Image Files</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Alternate</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>public.image</string>
            <string>public.jpeg</string>
            <string>public.png</string>
            <string>public.gif</string>
            <string>com.apple.heic</string>
            <string>com.apple.heif</string>
        </array>
        <key>LSFileQuarantineEnabled</key>
        <false/>
    </dict>
</array>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>

2. 添加UTI导出声明(关键)

在Info.plist中添加UTExportedTypeDeclarations,明确声明支持的图片类型,帮助系统识别应用的处理能力:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeIdentifier</key>
        <string>public.image</string>
        <key>UTTypeDescription</key>
        <string>Image File</string>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.item</string>
        </array>
    </dict>
</array>

3. 处理多图场景的代码适配

原代码仅处理单图,需要适配多选场景,同时注意文件权限问题(不要直接用Data(contentsOf:),改用安全作用域访问):

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    for context in URLContexts {
        let url = context.url
        // 处理安全作用域文件
        guard url.startAccessingSecurityScopedResource() else {
            print("无法访问文件")
            return
        }
        defer { url.stopAccessingSecurityScopedResource() }
        
        do {
            let data = try Data(contentsOf: url)
            if let image = UIImage(data: data) {
                let alert = UIAlertController(title: "导入图片成功", message: "尺寸:\(image.size)", preferredStyle: .alert)
                alert.addAction(UIAlertAction(title: "确定", style: .default))
                window?.rootViewController?.present(alert, animated: true)
            }
        } catch {
            print("读取图片失败:\(error.localizedDescription)")
        }
    }
}

4. 清除系统缓存的方法

配置修改后,为确保系统立即刷新,可执行以下操作:

  • 删除设备上的应用,重新安装
  • 重启设备(彻底清除Launch Services缓存)
  • 使用Xcode的Product > Clean Build Folder,再重新运行

关键说明

  • CFBundleTypeRole设为Viewer比Editor更符合分享场景的定位,系统优先级更高
  • LSHandlerRank设为Alternate,避免和系统默认应用冲突,同时保证在分享菜单中显示
  • 明确指定具体图片UTI,比通用UTI更易被系统识别,覆盖所有常见图片格式
  • LSFileQuarantineEnabled设为false,防止系统将从其他应用分享的文件视为隔离文件,导致应用无法被选中
  • 必须处理安全作用域文件,尤其是iOS 13+,否则会无法读取来自其他应用的文件

内容的提问来源于stack exchange,提问作者Bill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 21:54:56