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

ActionSheet在iPadOS上崩溃但iPhone运行正常的iOS开发问题咨询

问题原因

  • 这不是iPadOS的系统bug,是代码写法没有兼容iPad端的弹窗规则:iPhone上UIActivityViewController默认以底部sheet样式弹出,不需要指定锚点,但iPad上该控件默认以弹出框(popover)样式展示,系统强制要求必须给弹出框设置锚点源(sourceView)或者导航栏按钮项(barButtonItem),否则就会抛出你遇到的异常。
  • 之前能运行大概率是旧版iPadOS对该规则的校验比较宽松,新版系统收紧了校验逻辑才会触发崩溃。

修复方案

我们需要在弹出UIActivityViewController之前,针对iPad设备单独配置popover的锚点参数,适配后的代码版本如下:

import SwiftUI

struct ContentView: View {
    // 用来存储触发按钮的UIView引用,作为popover的锚点
    @State private var sourceView: UIView?
    
    var body: some View {
        Button(action: actionSheet) {
            Label("", systemImage: "square.and.arrow.up")
        }
        // 拿到SwiftUI View对应的底层UIView
        .background(UIViewGetter(view: $sourceView))
    }
    
    func actionSheet() {
        let av = UIActivityViewController(activityItems: ["Testing"], applicationActivities: nil)
        
        // 针对iPad设备配置popover参数
        if UIDevice.current.userInterfaceIdiom == .pad {
            av.popoverPresentationController?.sourceView = sourceView
            // 设置弹出框指向锚点的位置,这里设为锚点view的bounds,即指向按钮本身
            av.popoverPresentationController?.sourceRect = sourceView?.bounds ?? .zero
        }
        
        UIApplication.shared.windows.first?.rootViewController?.present(av, animated: true, completion: nil)
    }
}

// 辅助工具:用来获取SwiftUI View对应的底层UIKit UIView
struct UIViewGetter: UIViewRepresentable {
    @Binding var view: UIView?
    
    func makeUIView(context: Context) -> UIView {
        let view = UIView(frame: .zero)
        view.backgroundColor = .clear
        DispatchQueue.main.async {
            // 拿到父view也就是按钮的UIView实例
            self.view = view.superview
        }
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {}
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

补充说明

  • 如果是把按钮放在导航栏的ToolbarItem里,也可以直接给popoverPresentationController的barButtonItem属性赋值,不用单独获取sourceView。
  • 如果不需要自定义activity项,也可以直接用SwiftUI原生的ShareLink控件,系统会自动处理多设备适配,不用自己写UIKit桥接代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:06:03