在SwiftUI中封装UISheetPresentationController实现半屏模态弹窗问题求助
iOS 15 UISheetPresentationController SwiftUI 封装方案
首先纠正核心实现误区:
UIViewControllerRepresentable协议要求返回的是 UIViewController 实例,而非UISheetPresentationController本身,后者是 UIKit 中控制模态页展示样式的附属对象,不需要手动初始化。- 模态弹出的 UIViewController 会自动生成
UISheetPresentationController实例,直接访问控制器的对应属性即可,不需要手动传入presentedViewController和presenting参数初始化。
完整实现代码
import SwiftUI import UIKit struct KitSheet<Content: View>: UIViewControllerRepresentable { // 弹窗承载的SwiftUI内容 let content: Content // 支持的弹窗高度尺寸,默认提供中等、最大两种 var detents: [UISheetPresentationController.Detent] = [.medium(), .large()] // 是否展示顶部拖拽条 var showsGrabber: Bool = true func makeUIViewController(context: Context) -> UIViewController { // 创建承载SwiftUI内容的Hosting控制器 let hostingController = UIHostingController(rootView: content) // 直接获取系统自动生成的UISheetPresentationController实例 guard let sheetController = hostingController.sheetPresentationController else { return hostingController } // 配置弹窗样式 sheetController.detents = detents sheetController.prefersGrabberVisible = showsGrabber sheetController.delegate = context.coordinator return hostingController } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { // 状态更新时同步刷新弹窗配置 guard let sheetController = uiViewController.sheetPresentationController else { return } sheetController.detents = detents sheetController.prefersGrabberVisible = showsGrabber } // 实现协调器处理代理回调 func makeCoordinator() -> Coordinator { Coordinator() } class Coordinator: NSObject, UISheetPresentationControllerDelegate { // 按需实现UISheetPresentationControllerDelegate的代理方法即可 } }
使用示例
直接配合SwiftUI原生的sheet修饰符使用即可:
struct DemoView: View { @State private var isSheetPresented = false var body: some View { Button("唤起半屏弹窗") { isSheetPresented.toggle() } .sheet(isPresented: $isSheetPresented) { KitSheet( content: VStack(spacing: 30) { Text("半屏弹窗内容") .font(.title) Button("关闭弹窗") { isSheetPresented.toggle() } .foregroundColor(.blue) } .padding(.top, 20), detents: [.medium()], showsGrabber: true ) .ignoresSafeArea() } } }
补充说明
如果需要自定义模态弹出逻辑,可通过响应链获取当前应用顶层的UIViewController作为presentingViewController,不需要手动传入占位参数初始化UISheetPresentationController。
内容的提问来源于stack exchange,提问作者pjc_1983
相关产品推荐
相关产品推荐

