嵌入全屏导航控制器的视图控制器设置pageSheet模态展示样式异常问题
实现方案
你的需求完全可以实现,核心逻辑是优先统一默认模态展示样式,特定场景单独覆写即可,具体说明如下:
根因说明
pageSheet失效是因为从已设置为.fullScreen的模态控制器层级弹出新控制器时,默认会继承当前层级的模态展示配置,单独给目标控制器设置样式未生效的核心原因是没有覆盖默认继承逻辑。
推荐方案(适配全局默认全屏、特定场景用pageSheet的需求)
步骤1:全局配置默认模态样式为全屏
在App启动入口AppDelegate的application(_:didFinishLaunchingWithOptions:)方法中添加全局配置,通过UIAppearance统一所有控制器的默认模态弹出样式:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 全局设置默认模态展示样式为全屏 UIViewController.appearance().modalPresentationStyle = .fullScreen return true }
步骤2:特定场景单独指定pageSheet样式
需要使用原生pageSheet效果的位置,单独给目标控制器设置modalPresentationStyle = .pageSheet即可,该配置优先级高于全局默认配置:
class FirstViewController { func presentSecondVC() { let secondVC = UIViewController() // 单独指定pageSheet,覆盖全局默认的fullScreen secondVC.modalPresentationStyle = .pageSheet // 若需要调整pageSheet的高度等属性(可选),iOS15+可通过UISheetPresentationController配置 if let sheet = secondVC.sheetPresentationController { sheet.detents = [.medium(), .large()] // 示例:支持中等/大两种高度 sheet.prefersGrabberVisible = true // 示例:显示顶部的拖拽小横条 } present(secondVC, animated: true, completion: nil) } }
备选方案(仅在当前自定义导航控制器流程内生效)
如果你不需要全局修改,仅希望当前CustomNavigationController流程下默认弹出全屏,其他模块不受影响,可以重写自定义导航控制器的present方法:
class CustomNavigationController: UINavigationController { override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) { // 仅当要弹出的控制器没有主动设置modalPresentationStyle时,默认设为fullScreen if viewControllerToPresent.modalPresentationStyle == .automatic { viewControllerToPresent.modalPresentationStyle = .fullScreen } super.present(viewControllerToPresent, animated: flag, completion: completion) } }
该方案下,单独给控制器设置.pageSheet的逻辑依然生效,不需要修改原有业务代码。
内容的提问来源于stack exchange,提问作者G.Rulli
相关产品推荐
相关产品推荐

