核心原理
Share Extension 机制
Share Extension 是 iOS 的系统级扩展(App Extension),允许应用在系统分享菜单中接收其他应用(如相册、Safari)的数据。当用户选择截图并点击分享按钮时,系统会唤起你的 Share Extension。

数据传递流程

宿主应用(如相册)提供 NSExtensionItem 对象,包含截图的附件数据(NSItemProvider)。

Share Extension 通过 extensionContext 获取这些数据,解析为 UIImage 或文件 URL。

与主应用共享数据:通过 App Group 的共享容器(FileManager)或 UserDefaults 传递数据。

沙盒隔离与通信
Share Extension 运行在独立进程,需通过以下方式与主应用通信:

App Groups:共享文件容器(如 containerURL(forSecurityApplicationGroupIdentifier:))。

Keychain Sharing:共享敏感数据(如用户凭证)。

使用流程详解
步骤 1:创建 Share Extension Target
在 Xcode 项目中:
File → New → Target → iOS → Share Extension
输入扩展名称(如 ScreenshotShareExtension),激活 Scheme。

步骤 2:配置 App Group
启用 App Group

主应用 Target → Signing & Capabilities → + Capability → App Groups

Share Extension Target → 重复上述操作。

创建共享 Group ID

格式:group.com.yourcompany.appname

确保主应用和扩展勾选相同的 Group ID。

步骤 3:配置 Share Extension 的 Info.plist
修改 Info.plist 中的 NSExtension 字段:
步骤 4:实现 Share Extension 逻辑
在 ShareViewController.swift 中处理截图数据:

class ShareViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        handleSharedImage()
    }

    private func handleSharedImage() {
        guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem,
              let itemProvider = extensionItem.attachments?.first else {
            extensionContext?.cancelRequest(withError: NSError(domain: "com.your.app", code: 0))
            return
        }

        // 检查是否为图片
        if itemProvider.hasItemConformingToTypeIdentifier("public.image") {
            itemProvider.loadItem(forTypeIdentifier: "public.image", options: nil) { [weak self] (item, error) in
                guard let self = self, error == nil else { return }
                
                DispatchQueue.main.async {
                    if let url = item as? URL, let image = UIImage(contentsOfFile: url.path) {
                        self.saveImageToAppGroup(image) // 保存到共享容器
                    } else if let image = item as? UIImage {
                        self.saveImageToAppGroup(image)
                    }
                    self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
                }
            }
        }
    }

    private func saveImageToAppGroup(_ image: UIImage) {
        guard let data = image.pngData(),
              let groupContainer = FileManager.default.containerURL(
                forSecurityApplicationGroupIdentifier: "group.com.yourcompany.appname"
              ) else { return }
        
        let imagePath = groupContainer.appendingPathComponent("screenshot_\(Date().timeIntervalSince1970).png")
        try? data.write(to: imagePath)
        
        // 可选:通过 UserDefaults 通知主应用
        UserDefaults(suiteName: "group.com.yourcompany.appname")?.set(imagePath.lastPathComponent, forKey: "latestScreenshot")
    }
}

步骤 5:主应用读取截图
在主应用中监听共享数据:

// 在 AppDelegate 或 ViewController 中
func checkForNewScreenshot() {
    guard let groupContainer = FileManager.default.containerURL(
        forSecurityApplicationGroupIdentifier: "group.com.yourcompany.appname"
    ) else { return }
    
    // 从 UserDefaults 获取文件名
    if let fileName = UserDefaults(suiteName: "group.com.yourcompany.appname")?.string(forKey: "latestScreenshot") {
        let screenshotURL = groupContainer.appendingPathComponent(fileName)
        if let image = UIImage(contentsOfFile: screenshotURL.path) {
            // 显示截图
            DispatchQueue.main.async {
                self.imageView.image = image
            }
            // 清理记录
            UserDefaults(suiteName: "group.com.yourcompany.appname")?.removeObject(forKey: "latestScreenshot")
        }
    }
}

步骤 6:测试流程
运行 Share Extension Scheme:
Xcode 顶部 Scheme 选择扩展 Target → 运行。

在模拟器或设备上:

截屏并保存到相册。

打开相册 → 选择截图 → 点击分享按钮 → 选择你的应用扩展。

检查主应用是否接收到截图。

标签: none

添加新评论