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

SwiftUI Sheet中展示UIActivityViewController出现布局警告,求最佳实现方案

在SwiftUI中正确展示UIActivityViewController的方法

在iOS 16、Xcode 14环境下,直接用SwiftUI的sheet展示UIActivityViewController会触发布局约束警告,这是因为sheet的容器布局和系统分享控制器的自适配逻辑冲突导致的。正确的做法是通过UIKit的present方式调用分享控制器,而非SwiftUI的sheet组件。

触发的警告信息

2022-10-23 23:41:07.692216+0300 Test UIActivityViewController[92164:30374157] [LayoutConstraints] Changing the translatesAutoresizingMaskIntoConstraints property of a UICollectionReusableView that is managed by a UICollectionView is not supported, and will result in incorrect self-sizing. View: <_UIActivityContentFooterView: 0x15cd56340; baseClass = UICollectionReusableView; frame = (16 244.333; 361 52); layer = <CALayer: 0x600001ab8180>>

正确实现代码

1. 封装UIActivityViewController的UIViewControllerRepresentable

import SwiftUI

struct ShareSheet: UIViewControllerRepresentable {
    let items: [Any]
    let completion: (UIActivity.ActivityType?, Bool) -> Void
    
    func makeUIViewController(context: Context) -> UIActivityViewController {
        let controller = UIActivityViewController(activityItems: items, applicationActivities: nil)
        controller.completionWithItemsHandler = { activityType, completed, _, _ in
            completion(activityType, completed)
        }
        return controller
    }
    
    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}

2. 在ContentView中调用分享控制器

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
                .onTapGesture {
                    showShareSheet()
                }
        }
    }
    
    private func showShareSheet() {
        let shareText = "Hello everybody"
        let shareSheet = ShareSheet(items: [shareText]) { activityType, completed in
            // 分享完成后的回调逻辑,比如更新状态、提示用户等
            if completed {
                print("分享成功")
            }
        }
        
        guard let rootViewController = UIApplication.shared.connectedScenes
                .filter({ $0.activationState == .foregroundActive })
                .first(where: { $0 is UIWindowScene })
                .flatMap({ $0 as? UIWindowScene })?.windows
                .first(where: { $0.isKeyWindow })?.rootViewController else {
            return
        }
        
        rootViewController.present(shareSheet, animated: true)
    }
}

关键说明

  • 避免使用SwiftUI的sheet展示UIActivityViewController,改用UIKit的present方法,从当前活跃的keyWindow的rootViewController发起调用,确保分享控制器的布局符合系统规范。
  • 增加了completion回调,可以在分享完成后处理后续逻辑,比如给用户反馈状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 03:40:48