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

如何修改ShareViewController,选择分享面板应用时保存媒体并启动选中应用

iOS SwiftUI 分享扩展导入媒体并跳转主应用实现方案

1. 前置配置:开启App Group共享容器

App Group是iOS扩展与主应用共享数据的唯一官方合法途径,需要同时在主应用和Share Extension两个Target的「Signing & Capabilities」中添加App Group能力,自定义组名格式为group.你的应用BundleID,例如group.com.xxx.myphotoapp,两个Target的组名必须完全一致。

同时在主应用Target的「Info」配置页添加自定义URL Scheme,例如设置为myphotoapp,后续用于扩展唤起主应用。

2. Share Extension 逻辑实现(无需复杂UIViewController操作)

你可以直接替换Share Extension默认生成的ViewController代码为以下内容,无需额外界面,处理完文件后会直接跳转主应用:

import UIKit
import UniformTypeIdentifiers

class ShareViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        handleSharedMedia()
    }

    private func handleSharedMedia() {
        // 获取App Group共享目录路径
        guard let groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.xxx.myphotoapp") else {
            completeRequest()
            return
        }
        let importDir = groupURL.appendingPathComponent("SharedImport", isDirectory: true)
        // 初始化共享导入目录
        try? FileManager.default.createDirectory(at: importDir, withIntermediateDirectories: true)

        // 遍历获取所有分享的媒体文件
        guard let extensionItems = extensionContext?.inputItems as? [NSExtensionItem] else {
            completeRequest()
            return
        }

        let dispatchGroup = DispatchGroup()
        for item in extensionItems {
            guard let attachments = item.attachments else { continue }
            for attachment in attachments {
                // 匹配所有媒体/文件类型,可根据需求调整
                let supportedTypes: [UTType] = [.image, .video, .mpeg4Movie, .png, .jpeg, .pdf]
                for type in supportedTypes {
                    if attachment.hasItemConformingToTypeIdentifier(type.identifier) {
                        dispatchGroup.enter()
                        attachment.loadFileRepresentation(forTypeIdentifier: type.identifier) { [weak self] url, error in
                            defer { dispatchGroup.leave() }
                            guard let fileURL = url, error == nil else { return }
                            // 生成唯一文件名避免覆盖
                            let fileName = "\(UUID().uuidString)_\(fileURL.lastPathComponent)"
                            let targetURL = importDir.appendingPathComponent(fileName)
                            do {
                                try FileManager.default.copyItem(at: fileURL, to: targetURL)
                            } catch {
                                print("文件拷贝失败: \(error)")
                            }
                        }
                    }
                }
            }
        }

        // 所有文件处理完成后唤起主应用
        dispatchGroup.notify(queue: .main) { [weak self] in
            guard let url = URL(string: "myphotoapp://importMedia") else {
                self?.completeRequest()
                return
            }
            self?.extensionContext?.open(url) { _ in
                self?.completeRequest()
            }
        }
    }

    private func completeRequest() {
        extensionContext?.completeRequest(returningItems: [], completionHandler: nil)
    }
}

3. SwiftUI 主应用接收跳转并切换页面

在主应用的入口App结构体中添加URL监听逻辑,触发跳转至媒体列表页:

import SwiftUI

@main
struct MyPhotoApp: App {
    // 用于控制导航跳转
    @State private var navPath = NavigationPath()

    var body: some Scene {
        WindowGroup {
            NavigationStack(path: $navPath) {
                // 你的根页面
                ContentView()
                    .navigationDestination(for: String.self) { route in
                        if route == "ImportMediaView" {
                            // 你的媒体目录显示页面
                            ImportMediaView()
                        }
                    }
                    .onOpenURL { url in
                        guard url.scheme == "myphotoapp", url.host == "importMedia" else { return }
                        // 跳转至导入媒体页
                        navPath.append("ImportMediaView")
                    }
            }
        }
    }
}

注意事项

  • 若需要限制可导入的文件类型,可修改Share Extension中supportedTypes数组的UTType枚举值
  • 若导入大文件较多,可在Share Extension中添加简单的加载指示器避免用户以为操作无响应
  • 若需要传递具体的导入文件路径给主应用,可将路径进行URL编码后拼接在唤起URL的参数中,主应用解析URL参数即可获取

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 03:36:03