如何修改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
相关产品推荐
相关产品推荐

