iOS 13 Modals - 以编程方式调用滑动解除

Posted

技术标签:

【中文标题】iOS 13 Modals - 以编程方式调用滑动解除【英文标题】:iOS 13 Modals - Calling swipe dismissal programmatically 【发布时间】:2019-09-15 07:03:06 【问题描述】:

我想在呈现模态的视图控制器中检测模态解除。

此方法在检测新的卡片模式上的新 ios 13 滑动关闭时效果惊人:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if segue.identifier == "MyIdentifier" 
        segue.destination.presentationController?.delegate = self
    


extension MyController: UIAdaptivePresentationControllerDelegate     
    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) 
        //clean up UI (de-selecting stuff) once modal has been dismissed
    

但是,如果模态通过操作以编程方式自行关闭,则不会调用presentationControllerDidDismiss:

@IBAction func btnDismissTap(_ sender: Any) 
    self.dismiss(animated: true, completion: nil)

这是一个错误还是有一种方法可以以编程方式调用“滑动”解除的任何内容,以便我可以以相同的方式检测所有解除?目前,我正在将额外的“解雇”委托方法写入我的模式中作为一种解决方法,这似乎没有必要。

【问题讨论】:

【参考方案1】:

但是,如果模态通过操作以编程方式自行关闭,则不会调用presentationControllerDidDismiss

 self.dismiss(animated: true, completion: nil)

不需要调用它,因为您自己在代码中解除了模式。您不能不知道模态已被解雇。您不需要接收解雇信号,因为您首先发出了解雇信号。

您通常不会收到委托方法调用报告您自己的代码所做的事情。委托方法报告用户操作。如果您自己在代码中所做的一切都以委托方法调用的形式返回,那就太疯狂了。

【讨论】:

我在另一个视图控制器(模态)中给出了解除信号,呈现模态的视图控制器不知道它被解除了。滑动关闭的工作方式似乎相似(采取的操作是在 Modal 上,但它让呈现视图控制器知道)。 是的,但那是完全不同的事情。它与刷卡无关。例如,在 iPad 上使用表单时,您也会遇到同样的问题,即使从未发明过滑动关闭。 请参阅我在***.com/questions/54602662/… 此处讨论的关于学习呈现的视图控制器被解雇的一般问题。 谢谢,我想我对“presentationControllerDidDismiss”这个名称感到困惑,但实际上它只会触发某些类型的解雇而不是其他类型的解雇。我会看看你的另一个帖子。 “我想我被这个名字弄糊涂了”是的,这就是我的回答所解释的。您通常不会收到委托方法调用报告您自己的代码所做的事情。委托方法报告用户操作。如果您自己在代码中所做的一切都以委托方法调用的形式返回,那就太疯狂了。【参考方案2】:

正如@matt 所提到的,没有必要通知通过代表驳回视图的人。因为已经知道了。 但是如果您需要调用该委托方法,您应该在关闭视图后手动调用它:

@IBAction func btnDismissTap(_ sender: Any) 
    self.dismiss(animated: true) 
        presentationController?.delegate?.presentationControllerDidDismiss?(presentationController!)
    

【讨论】:

【参考方案3】:

Mojtaba Hosseini,我一直在寻找答案。

目前,我需要编写一个委托函数来让呈现视图知道用户关闭了模态 PLUS 执行用于滑动关闭的 PresentationControllerDidDismiss 处理程序:

@IBAction func btnDismissTap(_ sender: Any) 
    self.dismiss(animated: true, completion: 
        self.delegate?.myModalViewDidDismiss()
    )

我想以同样的方式处理这两种情况,Mojtaba 的回答对我有用。但是,如果您在 self.dismiss 完成块中调用它,presentationControllerDidDismiss 不会被调用,您需要在之前调用它。

我调整了我的代码以使用“presentationControllerWillDismiss”(为了清楚起见),并在我以编程方式在我的模式中关闭之前简单地调用了委托,它工作得很好。

@IBAction func btnDismissTap(_ sender: Any) 
    if let pvc = self.presentationController 
        pvc.delegate?.presentationControllerWillDismiss?(pvc)
    
    self.dismiss(animated: true, completion: nil)

现在,我不再需要创建委托函数来处理代码中的模态解除,我的滑动处理程序可以处理所有场景。

仅供参考,一旦模式被解除,我正在“处理”的是在呈现的 UI 上进行一些 UI 清理(取消选择等)。

【讨论】:

if let pvc = self.presentationController pvc.delegate?.presentationControllerDidDismiss?(pvc) // 应该是 DidDismiss 而不是 WillDismiss 模态还没有被解除,发生在下一行。 @WilliamT。因为在调用presentationControllerDidDismiss()之前可以多次调用presentationControllerWillDismiss()。有人可能出于其他原因想在这里做某事。在您的情况下,您自己触发了解雇代表,并且您很确定 vc 即将被解雇,因此我同意 AmitVerma 的建议。不要乱用 willDissmiss 和 didDismiss。它们代表不同的情况。

以上是关于iOS 13 Modals - 以编程方式调用滑动解除的主要内容,如果未能解决你的问题,请参考以下文章

UITableView以编程方式调用滑动操作

是否可以以编程方式强制 iOS 应用程序在拆分视图/滑动中在 ios9 中全屏显示?

以编程方式滑动 UISlider

在 iOS 13 上以编程方式滚动 SwiftUI ScrollView

如何以编程方式在 iOS 13 中隐藏和显示状态栏?

目标 c:iOS 13+ 以编程方式设置初始根视图控制器