iPad旋转时ActionSheet的PopoverController无法保持窗口居中问题咨询
为什么iPad旋转后Popover无法保持在窗口中央?
这个问题我之前也踩过坑!核心原因很简单:你一开始设置的sourceRect是基于旋转前的窗口尺寸计算的中心,而iPad旋转后,窗口的bounds会发生宽高互换的变化,但iOS的Popover控制器不会自动帮你重新计算更新这个位置——它只会记住你第一次设置的坐标,旋转后这个坐标就不再对应新窗口的中心,自然就跑偏到左下角了。
解决方法:监听旋转事件,实时更新Popover位置
你需要在设备旋转时,重新获取新窗口的中心坐标,更新Popover的sourceRect。这里有两种靠谱的实现方式:
1. 利用视图控制器的生命周期方法
在你展示Popover的视图控制器里,重写viewWillTransition(to:with:)方法——这个方法会在设备旋转、窗口尺寸变化前被调用,刚好适合我们更新位置:
// 先给CGRect加个扩展,方便快速获取中心坐标 extension CGRect { var center: CGPoint { CGPoint(x: midX, y: midY) } } // 在你的视图控制器里 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) // 确保你持有Popover对应的AlertController引用 guard let alertController = yourActionSheetAlertController, let popoverController = alertController.popoverPresentationController, let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return } // 计算新窗口的中心,更新sourceRect let newWindowCenter = keyWindow.bounds.center popoverController.sourceRect = CGRect(x: newWindowCenter.x, y: newWindowCenter.y, width: 0, height: 0) // 强制Popover更新布局,确保位置生效 coordinator.animate(alongsideTransition: { _ in popoverController.containerView?.layoutIfNeeded() }) }
2. 监听设备旋转通知
如果你的场景不适合用视图控制器的生命周期方法,也可以注册旋转通知,在回调里更新位置:
override func viewDidLoad() { super.viewDidLoad() // 注册旋转通知 NotificationCenter.default.addObserver(self, selector: #selector(updatePopoverPosition), name: UIDevice.orientationDidChangeNotification, object: nil) } @objc private func updatePopoverPosition() { guard let alertController = yourActionSheetAlertController, let popoverController = alertController.popoverPresentationController, let keyWindow = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else { return } let newWindowCenter = keyWindow.bounds.center popoverController.sourceRect = CGRect(x: newWindowCenter.x, y: newWindowCenter.y, width: 0, height: 0) } // 记得在视图销毁时移除通知 deinit { NotificationCenter.default.removeObserver(self) }
额外注意点
- 一定要持有ActionSheet对应的
UIAlertController引用,不然你没法在旋转时拿到它的popoverPresentationController。 - 你之前设置的
permittedArrowDirections = []是正确的,这样Popover就不会显示箭头,完全居中展示。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

