简体   繁体   English

iOS 13 的presentationControllerDidDismiss() 在紧凑环境中不调用Popover

[英]iOS 13's presentationControllerDidDismiss() Not Called for Popover in Compact Environment

I am updating my app for iOS 13's new “card-style” modal views.我正在为 iOS 13 的新“卡片式”模式视图更新我的应用程序。 All has been working well using UIAdaptivePresentationControllerDelegate 's presentationControllerDidAttemptToDismiss() and presentationControllerDidDismiss() functions.使用UIAdaptivePresentationControllerDelegatepresentationControllerDidAttemptToDismiss()presentationControllerDidDismiss()函数,一切都运行良好。 But, for views that have their .modalPresentationStyle set to .popover , presentationControllerDidDismiss() is not called when being presented in compact environments (such as a phone or iPad in split or slide-over).但是,对于将.modalPresentationStyle设置为.popover视图,在紧凑环境(例如拆分或滑动的手机或 iPad)中呈现时, presentationControllerDidDismiss()不会被调用。 It's called correctly when presented in a regular size class environment (such as an iPad full-screen).在常规尺寸类环境(例如 iPad 全屏)中呈现时,它会被正确调用。

My code setting this up is pretty straightforward:我的代码设置非常简单:

The code presenting the popover:呈现弹出框的代码:

func showChooser() {
    // other setup code...
    navController.modalPresentationStyle = .popover
    navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
    self.present(navController, animated: true)
}

Then, the presented controller conforms to UIAdaptivePresentationControllerDelegate and sets up:然后,呈现的控制器符合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?()
}

When the view is presented in regular size-class environments, it is displayed correctly as a popover.当视图在常规大小类环境中呈现时,它会正确显示为弹出框。 When the user taps outside the popover, then presentationControllerDidDismiss() is called.当用户点击弹出框外时,将调用presentationControllerDidDismiss() However, when the same code is presented in a compact environment, it's displayed correctly (as a card style), but when the user drags down the view, presentationControllerDidDismiss() is not called.但是,当相同的代码在紧凑的环境中呈现时,它会正确显示(作为卡片样式),但是当用户向下拖动视图时, presentationControllerDidDismiss()不会被调用。

If I change the .modalPresentationStyle to something else such as .pageSheet or .formSheet , then it all works as expected in either compact or regular presentations.如果我将.modalPresentationStyle更改为其他内容,例如.pageSheet.formSheet ,那么它在紧凑或常规演示文稿中都按预期工作。

I've tried using the delegate's adaptivePresentationStyle() to change the style to .formSheet on compact environments, but presentationControllerDidDismiss() is still not called correctly.我已经尝试使用委托的adaptivePresentationStyle()在紧凑的环境中将样式更改为.formSheet ,但是presentationControllerDidDismiss()仍然没有被正确调用。

Update : I should have mentioned that my current workaround is to check the size class and change .modalPresentationStyle as needed:更新:我应该提到我当前的解决方法是检查大小类并根据需要更改.modalPresentationStyle

if self.traitCollection.horizontalSizeClass == .compact {
    navController.modalPresentationStyle = .automatic
} else {
    navController.modalPresentationStyle = .popover
    navController.popoverPresentationController?.barButtonItem = self.viewController?.navigationItem.leftBarButtonItem
}

This works, but it seems that just using the .popover style should adapt properly and call the correct delegate methods.这有效,但似乎只使用.popover样式应该正确适应并调用正确的委托方法。

Update 2: I've updated the code above to clarify that the presented view controller is the one handling the delegate methods.更新 2:我已经更新了上面的代码,以阐明所呈现的视图控制器是处理委托方法的控制器。

Also, after digging into this more, I noticed that if the presenting view controller is the delegate and handles the delegate methods, then this all works as expected.此外,在深入研究之后,我注意到如果呈现视图控制器是委托并处理委托方法,那么这一切都按预期工作。 Since it also works in the presented view controller for all .modalPresentationStyle 's except popover in compact environments, perhaps there is some lifetime issue when popovers are presented in that way?由于它也适用于所有.modalPresentationStyle呈现视图控制器,除了紧凑环境中的 popover ,当以这种方式呈现 popover 时,也许存在一些生命周期问题?

Any ideas about what I might be doing wrong?关于我可能做错了什么的任何想法?

The problem is merely one of timing.问题只是时机之一。 You're doing this in the second view controller:您正在第二个视图控制器中执行此操作:

override func viewDidLoad() {
    self.navigationController?.presentationController?.delegate = self
}

That's too late .太晚了 You can set the delegate where you configure and perform the presentation:您可以在配置和执行演示的位置设置代理:

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)
}

If you prefer to insist upon having the second view controller set itself as delegate, do it earlier.如果您更愿意坚持让第二个视图控制器将自己设置为委托,请尽早执行。 The first good opportunity is willMove :第一个好机会是willMove

override func willMove(toParent parent: UIViewController?) {
    self.parent?.presentationController?.delegate = self
}

Thanks heaps for that example - just to extend on the details from Matt and for the benefit of those looking for a generic example (with the creation of a standalone viewController), I believe something like the below should also work:感谢那个例子的堆 - 只是为了扩展 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)
}

navController.presentationController?.delegate = // * navController.viewControllers[0] self.present(navController, animated: true)否则你的presentationController可能是nil

if your viewController is nested inside another navigationviewController如果您的 viewController 嵌套在另一个 navigationviewController 中

override func viewDidLoad() {
    super.viewDidLoad()
    presentationController?.delegate = self
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM