iOS 13 的 presentationControllerDidDismiss() 未在 Compact 环境中为 Popover 调用
iOS 13's presentationControllerDidDismiss() Not Called for Popover in Compact Environment
我正在为 iOS 13 的新“卡片式”模态视图更新我的应用程序。使用 UIAdaptivePresentationControllerDelegate
的 presentationControllerDidAttemptToDismiss()
和 presentationControllerDidDismiss()
函数,一切都运行良好。但是,对于将 .modalPresentationStyle
设置为 .popover
的视图,在紧凑环境(例如 phone 或 iPad 中呈现时不会调用 presentationControllerDidDismiss()
拆分或滑过)。在常规尺寸 class 环境(例如 iPad 全屏)中显示时,它会被正确调用。
我的代码设置非常简单:
呈现弹出窗口的代码:
func showChooser() {
// other setup code...
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
self.present(navController, animated: true)
}
然后,呈现的控制器符合UIAdaptivePresentationControllerDelegate
并设置:
// This is in the presented view controller (i.e. the popover)
override func viewDidLoad() {
// other setup removed for brevity…
self.navigationController?.presentationController?.delegate = self
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
print("did dismiss")
self.cancel?()
}
当视图在常规尺寸 -class 环境中呈现时,它会正确显示为弹出窗口。当用户在弹出窗口外点击时,将调用 presentationControllerDidDismiss()
。但是,当相同的代码在紧凑的环境中呈现时,它可以正确显示(作为卡片样式),但是当用户向下拖动视图时,不会调用presentationControllerDidDismiss()
。
如果我将 .modalPresentationStyle
更改为其他内容,例如 .pageSheet
或 .formSheet
,那么它在紧凑或常规演示文稿中都会按预期工作。
我试过在紧凑环境下使用委托的 adaptivePresentationStyle()
将样式更改为 .formSheet
,但仍然无法正确调用 presentationControllerDidDismiss()
。
更新:
我应该提到我当前的解决方法是检查大小 class 并根据需要更改 .modalPresentationStyle
:
if self.traitCollection.horizontalSizeClass == .compact {
navController.modalPresentationStyle = .automatic
} else {
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
}
这行得通,但似乎只使用 .popover
样式应该可以正确适应并调用正确的委托方法。
更新二:
我更新了上面的代码以阐明 presented 视图控制器是处理委托方法的视图控制器。
此外,在深入研究之后,我注意到如果 presenting 视图控制器是委托并处理委托方法,那么这一切都按预期工作。由于它也适用于紧凑环境中所有 .modalPresentationStyle
的 except 弹出窗口的 presented 视图控制器,因此可能存在一些生命周期问题何时以这种方式显示弹出窗口?
关于我可能做错了什么的想法?
问题只是时间问题之一。您在第二个视图控制器中执行此操作:
override func viewDidLoad() {
self.navigationController?.presentationController?.delegate = self
}
太晚了。您可以在配置和执行演示的地方设置委托:
func showChooser() {
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem =
self.viewController?.navigationItem.leftBarButtonItem
navController.presentationController?.delegate = // *
navController.viewControllers[0]
as! UIAdaptivePresentationControllerDelegate
self.present(navController, animated: true)
}
如果您更愿意坚持让第二个视图控制器将自己设置为委托,请早点进行。第一个好机会是willMove
:
override func willMove(toParent parent: UIViewController?) {
self.parent?.presentationController?.delegate = self
}
将navController.presentationController?.delegate = // *
navController.viewControllers[0]
放在self.present(navController, animated: true)
之后,否则你的presentationController
可能是nil
非常感谢该示例 - 只是为了扩展 Matt 的详细信息并为那些寻找通用示例(通过创建独立 viewController)的人带来好处,我相信如下所示也应该有效:
func presentExampleViewController() {
// Any other setup code specific to the view in your app can go here...
let exampleViewController = SomeCustomViewController()
exampleViewController.presentationController?.delegate = exampleViewController
self.present(exampleViewController, animated: true)
}
如果您的 viewController 嵌套在另一个导航中viewController
override func viewDidLoad() {
super.viewDidLoad()
presentationController?.delegate = self
}
我正在为 iOS 13 的新“卡片式”模态视图更新我的应用程序。使用 UIAdaptivePresentationControllerDelegate
的 presentationControllerDidAttemptToDismiss()
和 presentationControllerDidDismiss()
函数,一切都运行良好。但是,对于将 .modalPresentationStyle
设置为 .popover
的视图,在紧凑环境(例如 phone 或 iPad 中呈现时不会调用 presentationControllerDidDismiss()
拆分或滑过)。在常规尺寸 class 环境(例如 iPad 全屏)中显示时,它会被正确调用。
我的代码设置非常简单:
呈现弹出窗口的代码:
func showChooser() {
// other setup code...
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
self.present(navController, animated: true)
}
然后,呈现的控制器符合UIAdaptivePresentationControllerDelegate
并设置:
// This is in the presented view controller (i.e. the popover)
override func viewDidLoad() {
// other setup removed for brevity…
self.navigationController?.presentationController?.delegate = self
}
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
print("did dismiss")
self.cancel?()
}
当视图在常规尺寸 -class 环境中呈现时,它会正确显示为弹出窗口。当用户在弹出窗口外点击时,将调用 presentationControllerDidDismiss()
。但是,当相同的代码在紧凑的环境中呈现时,它可以正确显示(作为卡片样式),但是当用户向下拖动视图时,不会调用presentationControllerDidDismiss()
。
如果我将 .modalPresentationStyle
更改为其他内容,例如 .pageSheet
或 .formSheet
,那么它在紧凑或常规演示文稿中都会按预期工作。
我试过在紧凑环境下使用委托的 adaptivePresentationStyle()
将样式更改为 .formSheet
,但仍然无法正确调用 presentationControllerDidDismiss()
。
更新:
我应该提到我当前的解决方法是检查大小 class 并根据需要更改 .modalPresentationStyle
:
if self.traitCollection.horizontalSizeClass == .compact {
navController.modalPresentationStyle = .automatic
} else {
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
}
这行得通,但似乎只使用 .popover
样式应该可以正确适应并调用正确的委托方法。
更新二: 我更新了上面的代码以阐明 presented 视图控制器是处理委托方法的视图控制器。
此外,在深入研究之后,我注意到如果 presenting 视图控制器是委托并处理委托方法,那么这一切都按预期工作。由于它也适用于紧凑环境中所有 .modalPresentationStyle
的 except 弹出窗口的 presented 视图控制器,因此可能存在一些生命周期问题何时以这种方式显示弹出窗口?
关于我可能做错了什么的想法?
问题只是时间问题之一。您在第二个视图控制器中执行此操作:
override func viewDidLoad() {
self.navigationController?.presentationController?.delegate = self
}
太晚了。您可以在配置和执行演示的地方设置委托:
func showChooser() {
navController.modalPresentationStyle = .popover
navController.popoverPresentationController?.barButtonItem =
self.viewController?.navigationItem.leftBarButtonItem
navController.presentationController?.delegate = // *
navController.viewControllers[0]
as! UIAdaptivePresentationControllerDelegate
self.present(navController, animated: true)
}
如果您更愿意坚持让第二个视图控制器将自己设置为委托,请早点进行。第一个好机会是willMove
:
override func willMove(toParent parent: UIViewController?) {
self.parent?.presentationController?.delegate = self
}
将navController.presentationController?.delegate = // *
navController.viewControllers[0]
放在self.present(navController, animated: true)
之后,否则你的presentationController
可能是nil
非常感谢该示例 - 只是为了扩展 Matt 的详细信息并为那些寻找通用示例(通过创建独立 viewController)的人带来好处,我相信如下所示也应该有效:
func presentExampleViewController() {
// Any other setup code specific to the view in your app can go here...
let exampleViewController = SomeCustomViewController()
exampleViewController.presentationController?.delegate = exampleViewController
self.present(exampleViewController, animated: true)
}
如果您的 viewController 嵌套在另一个导航中viewController
override func viewDidLoad() {
super.viewDidLoad()
presentationController?.delegate = self
}