在 iPadOS 17 上,关闭弹出框然后快速再次呈现弹出框时会发生崩溃。通常错误如下:
UIPopoverPresentationController 应该在演示发生之前设置一个非零的 sourceView 或 barButtonItem
但是我偶尔会看到以下内容:
应用程序尝试以模态方式呈现[主视图 Controller ]已呈现的 View Controller
这是重现此崩溃所需的最少源代码:
class ViewController: UIViewController {
let popoverVC = UIViewController()
@IBOutlet var showPopoverButton: UIButton!
@IBAction func showPopoverTapped(_ sender: UIButton) {
popoverVC.modalPresentationStyle = .popover
popoverVC.popoverPresentationController?.sourceView = showPopoverButton
present(popoverVC, animated: true)
}
}
关于此问题需要考虑的一些其他事项:
- 在 iOS 16 或更早版本上不会出现这种情况。
- 在
popoverPresentationController
上设置.sourceRect
没有任何效果。 - 设置弹出窗口的
frame
或preferredContentSize
无效。 - 崩溃发生在带有或不带有 Storyboard(硬编码 UI)的 UIKit 中。
- SwiftUI 中不会发生崩溃。请不要建议使用 SwiftUI 作为修复方案。
- 我可以在演示之前添加一个
guard
以确保sourceView
不是nil
,但它没有效果。
出现此问题的原因似乎是,在呈现新的弹出窗口时,弹出窗口 View Controller 未从内存中完全解除分配。这正在造成某种碰撞。我已经成功调配了 UIPopoverPresentationController.dismissalTransitionWillBegin
并且我很乐意发布该解决方案,但首先我想看看是否有更少的解决方法。我不想简单地覆盖 dismissalTransitionWillBegin
因为我想要默认行为,并且不想仅仅为了满足此错误而重写我自己的弹出窗口动画。
最佳答案
我在 iPadOS 17 上也遇到了同样的崩溃。这种情况不会一直发生,所以为什么会发生这种情况很棘手。
我当前的解决方法是在继续呈现新 View Controller 之前检查当前 View Controller 是否正在呈现另一个 View Controller 。到目前为止,这似乎对我有用。
guard self.presentedViewController == nil else { return }
关于iOS 17 UIKit Popover 在 iPad 上崩溃 - UIPopoverPresentationController 应该有一个非零的 sourceView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77284551/