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

iOS沙盒环境调用分享菜单时出现异常报错

iOS分享图片功能异常修复方案

环境信息

  • Xcode 15.3
  • Swift 5.10
  • iOS 17.4.1(真机测试)

问题现象

点击待办项中的图片打开全屏查看器后,点击底部分享按钮无任何响应,日志输出权限及弹窗冲突类错误,核心错误如下:

Attempt to present <UIActivityViewController: 0x10582e800> on <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10301e800> (from <_TtGC7SwiftUI19UIHostingControllerGVS_15ModifiedContentVS_7AnyViewVS_12RootModifier__: 0x10301e800>) which is already presenting <_TtGC7SwiftUI29PresentationHostingControllerVS_7AnyView_: 0x10700ee00>.

问题原因

代码直接使用rootViewController弹出分享表,但此时rootViewController已经弹出了全屏图片查看器(fullScreenCover),iOS不允许同一控制器同时present两个弹窗,必须在当前最顶层的presented控制器上发起新的present操作。

修复方案

方案1:获取顶层控制器弹出分享表

添加UIViewController扩展,用于定位当前活跃的最顶层控制器:

extension UIViewController {
    static func topMostViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.connectedScenes
            .filter { $0.activationState == .foregroundActive }
            .first(where: { $0 is UIWindowScene })
            .flatMap({ $0 as? UIWindowScene })?.windows
            .first(where: { $0.isKeyWindow })
        
        var topController = keyWindow?.rootViewController
        while let presentedViewController = topController?.presentedViewController {
            topController = presentedViewController
        }
        return topController
    }
}

修改shareImage方法,使用顶层控制器弹出分享表:

private func shareImage(_ image: UIImage) {
    let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
    guard let topController = UIViewController.topMostViewController() else { return }
    topController.present(activityController, animated: true, completion: nil)
}

方案2:SwiftUI原生sheet方式(更贴合SwiftUI风格)

创建UIActivityViewController的SwiftUI包装器:

struct ActivityViewController: UIViewControllerRepresentable {
    var activityItems: [Any]
    var applicationActivities: [UIActivity]? = nil
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        UIActivityViewController(activityItems: activityItems, applicationActivities: applicationActivities)
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}

在ContentView中添加状态变量控制分享弹窗:

@State private var sharedImage: UIImage? = nil

修改图片查看器内的分享按钮逻辑:

Button(action: {
    sharedImage = uiImage
}) {
    Label("Share", systemImage: "square.and.arrow.up")
        .foregroundColor(.blue)
}
.buttonStyle(.plain)

最后在ContentView的body末尾添加sheet:

.sheet(item: $sharedImage) { image in
    ActivityViewController(activityItems: [image])
}

关键代码片段(方案1示例)

// 顶层控制器扩展
extension UIViewController {
    static func topMostViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.connectedScenes
            .filter { $0.activationState == .foregroundActive }
            .first(where: { $0 is UIWindowScene })
            .flatMap({ $0 as? UIWindowScene })?.windows
            .first(where: { $0.isKeyWindow })
        
        var topController = keyWindow?.rootViewController
        while let presentedViewController = topController?.presentedViewController {
            topController = presentedViewController
        }
        return topController
    }
}

struct ContentView: View {
    // 原有状态变量、查询属性保持不变
    
    private func shareImage(_ image: UIImage) {
        let activityController = UIActivityViewController(activityItems: [image], applicationActivities: nil)
        guard let topController = UIViewController.topMostViewController() else { return }
        topController.present(activityController, animated: true, completion: nil)
    }
    
    // 原有视图、方法逻辑保持不变
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:40:54