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

UIActivityViewController在SwiftUI中无法正常工作?疑似存在严重Bug

解决SwiftUI中UIActivityViewController分享至WhatsApp的异常问题

兄弟,你遇到的这个问题我之前也踩过坑!确实和SwiftUI与UIKit模态视图的交互兼容性脱不了干系,尤其是第三方ShareExtension(比如WhatsApp的)和SwiftUI的sheet/fullScreenCover呈现机制之间的生命周期冲突。那些错误日志本质是WhatsApp的分享扩展连接被意外中断,根源往往是SwiftUI没处理好UIActivityViewController的模态生命周期。

下面是几个亲测有效的解决方案,按优先级尝试:

1. 先切真机测试!(最容易忽略的前提)

WhatsApp的ShareExtension在模拟器上基本没法正常工作,很多时候模拟器上的异常只是因为扩展根本没被正确加载。先换到真机跑一遍,排除环境问题再说。

2. 绕开SwiftUI模态,用UIKit原生方式呈现

SwiftUI的sheet/fullScreenCover和UIActivityViewController这种UIKit原生模态控制器嵌套时,很容易出现生命周期冲突。我们可以自定义一个UIViewControllerRepresentable,直接用UIKit的present方法来显示分享控制器:

struct ActivityView: UIViewControllerRepresentable {
    let shareItems: [Any]
    @Binding var isShowing: Bool
    
    func makeCoordinator() -> Coordinator {
        Coordinator(parent: self)
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        // 用一个空白的UIViewController作为容器
        UIViewController()
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        if isShowing {
            let activityVC = UIActivityViewController(
                activityItems: shareItems,
                applicationActivities: nil
            )
            // 处理分享完成后的关闭逻辑
            activityVC.completionWithItemsHandler = { _, _, _, _ in
                self.isShowing = false
            }
            // 设置代理,处理用户手动关闭的情况
            activityVC.presentationController?.delegate = context.coordinator
            uiViewController.present(activityVC, animated: true)
        } else {
            uiViewController.dismiss(animated: true)
        }
    }
    
    class Coordinator: NSObject, UIAdaptivePresentationControllerDelegate {
        let parent: ActivityView
        
        init(parent: ActivityView) {
            self.parent = parent
        }
        
        func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
            parent.isShowing = false
        }
    }
}

然后在你的SwiftUI视图里这么用:

struct ContentView: View {
    @State private var showShareSheet = false
    
    var body: some View {
        Button("分享到WhatsApp") {
            showShareSheet = true
        }
        // 把ActivityView作为背景嵌入,避免影响主视图布局
        .background(
            ActivityView(shareItems: ["这是测试分享内容"], isShowing: $showShareSheet)
        )
    }
}

这种方式完全绕开了SwiftUI的模态系统,用UIKit原生的逻辑来管理分享控制器的生命周期,对第三方扩展的兼容性要好得多。

3. 如果非要用SwiftUI模态,试试fullScreenCover替代sheet

如果你不想改太多代码,也可以尝试把sheet换成fullScreenCover,有时候这种全屏模态的呈现方式能减少和UIKit组件的冲突:

struct ContentView: View {
    @State private var showShareSheet = false
    
    var body: some View {
        Button("分享") {
            showShareSheet = true
        }
        .fullScreenCover(isPresented: $showShareSheet) {
            ActivityViewController(activityItems: ["测试内容"])
                .ignoresSafeArea()
        }
    }
}

// 基础的UIActivityViewController封装
struct ActivityViewController: UIViewControllerRepresentable {
    let activityItems: [Any]
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
        // 可以排除不需要的分享选项,减少冲突概率
        controller.excludedActivityTypes = [.addToReadingList, .assignToContact]
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}

4. 检查Info.plist的URL Scheme配置

虽然不是直接导致连接中断的原因,但确保你的App配置了WhatsApp的URL Scheme(whatsapp://),有时候缺少这个会导致分享流程异常。在Info.plist的LSApplicationQueriesSchemes数组里添加whatsapp即可。

总之,这类问题的核心就是SwiftUI和UIKit在模态生命周期管理上的差异,尤其是涉及第三方扩展的场景,用UIKit原生的呈现方式往往能解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:02:33