You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现让自定义分享操作显示在iOS其他应用的分享面板中?

如何实现让自定义分享操作显示在iOS其他应用的分享面板中?

我完全懂你的需求——就像ILovePDF、Chrome那样,让自己App的自定义操作(比如“用我的App打开”“用我的App编辑”)出现在其他App的iOS分享面板第三排对吧?网上大多教程都是教你给自己的App加分享操作,确实容易搞混,我来一步步给你理清楚实现方法:

一、实现“Open in 你的App”这类跳转操作

这种是让用户把其他App里的内容直接导入到你的App中,核心是告诉iOS系统你的App能处理哪些类型的内容:

  1. 在主App的Info.plist中声明支持的文件类型
    你需要在Info.plist里添加CFBundleDocumentTypes,指定你的App能处理的UTI(统一类型标识符,比如PDF、图片、文本等)。
    右键点击Info.plist选择「Open As -> Source Code」,添加类似以下代码:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>PDF文档</string>
            <key>CFBundleTypeRole</key>
            <string>Viewer</string> <!-- 这里填Viewer/Editor,根据你的App功能选择 -->
            <key>LSHandlerRank</key>
            <string>Alternate</string> <!-- 设为Alternate会让App出现在自定义操作区,Default是默认处理者 -->
            <key>LSItemContentTypes</key>
            <array>
                <string>public.pdf</string> <!-- 支持PDF,你可以添加更多UTI,比如public.image、public.text -->
            </array>
        </dict>
    </array>
    
  2. 处理App间的数据传递
    当用户在其他App选择“Open in 你的App”时,iOS会把文件传递过来,你需要在SceneDelegate(或AppDelegate,取决于你的项目架构)里处理这个请求:

    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let sourceURL = URLContexts.first?.url else { return }
        // 把传入的文件复制到自己App的沙盒目录,避免原文件被删除
        let docsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
        let destinationURL = docsDir.appendingPathComponent(sourceURL.lastPathComponent)
        
        do {
            try FileManager.default.copyItem(at: sourceURL, to: destinationURL)
            // 这里跳转到你的App对应的页面展示文件即可
        } catch {
            print("复制文件失败: \(error.localizedDescription)")
        }
    }
    

二、实现“Edit with 你的App”这类编辑操作

这种是用户在其他App里调用你的App处理内容,处理完成后还能返回原App,需要用到Action Extension

  1. 给项目添加Action Extension
    在Xcode中选择「File -> New -> Target」,找到「Action Extension」,输入名称(比如EditWithMyApp),点击Finish完成创建。

  2. 配置Extension的Info.plist
    打开Extension的Info.plist,找到NSExtension字典,配置以下关键项:

    <key>NSExtension</key>
    <dict>
        <key>NSExtensionAttributes</key>
        <dict>
            <key>NSExtensionActivationRule</key>
            <dict>
                <!-- 配置支持的内容类型,这里以PDF为例,可添加更多 -->
                <key>NSExtensionActivationSupportsPDFWithMaxCount</key>
                <integer>1</integer>
                <key>NSExtensionActivationSupportsImageWithMaxCount</key>
                <integer>1</integer>
            </dict>
        </dict>
        <key>NSExtensionPrincipalClass</key>
        <string>$(PRODUCT_MODULE_NAME).ActionViewController</string> <!-- 处理逻辑的ViewController -->
        <key>NSExtensionPointIdentifier</key>
        <string>com.apple.ui-services</string>
    </dict>
    
  3. 实现Extension的处理逻辑
    在自动生成的ActionViewController中,编写内容处理代码,处理完成后返回结果给原App:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 获取其他App传入的内容
        guard let inputItems = extensionContext?.inputItems as? [NSExtensionItem] else { return }
        for item in inputItems {
            guard let attachments = item.attachments else { continue }
            for provider in attachments {
                if provider.hasItemConformingToTypeIdentifier("public.pdf") {
                    provider.loadItem(forTypeIdentifier: "public.pdf", options: nil) { [weak self] data, error in
                        DispatchQueue.main.async {
                            guard let self = self, let fileURL = data as? URL else { return }
                            // 这里编写你的PDF编辑逻辑,比如修改内容后生成新的文件URL
                            let editedFileURL = self.processPDF(fileURL)
                            
                            // 将处理后的结果返回给原App
                            let outputItem = NSExtensionItem()
                            let outputProvider = NSItemProvider(contentsOf: editedFileURL)!
                            outputItem.attachments = [outputProvider]
                            self.extensionContext?.completeRequest(returningItems: [outputItem], completionHandler: nil)
                        }
                    }
                }
            }
        }
    }
    
    // 示例:模拟PDF处理方法
    private func processPDF(_ url: URL) -> URL {
        // 这里替换成你的真实处理逻辑
        return url
    }
    

测试注意事项

  • 要把主App和Extension一起安装到设备/模拟器上,单独安装Extension是不行的;
  • 如果你的操作没有出现在分享面板,检查UTI配置是否和测试的文件类型匹配,NSExtensionActivationRule是否正确;
  • 对于Extension,记得在Capabilities里开启App Groups(如果需要和主App共享数据的话)。

备注:内容来源于stack exchange,提问作者prashant dixit

火山引擎 最新活动