【问题标题】:How to get notified when a presented view controller is dismissed with a gesture?当使用手势关闭呈现的视图控制器时如何获得通知?
【发布时间】:2020-10-02 00:16:05
【问题描述】:

在某些情况下(iPhone X、iOS 13)可以通过从顶部拉动手势来关闭呈现的视图控制器。

在这种情况下,我似乎找不到通知呈现视图控制器的方法。我错过了什么吗?

我发现的唯一方法是向呈现的视图控制器的 viewDidDisappear 添加一个委托方法。

类似:

class Presenting: UIViewController, PresentedDelegate {
    func someAction() {
        let presented = Presented()
        presented.delegate = self
        present(presented, animated: true, completion: nil)
    }
    func presentedDidDismiss(_ presented: Presented) {
        // Presented was dismissed
    }
}

protocol PresentedDelegate: AnyObject {
    func presentedDidDismiss(_ presented: Presented)
}

class Presented: UIViewController {
    weak var delegate: PresentedDelegate?

    override func viewDidDisappear(animated: Bool) {
         ...
         delegate?.presentedDidDismiss(self)
    }
}

也可以通过通知来管理这个,使用 vc 子类,但仍然不能令人满意。


extension Notification.Name {
    static let viewControllerDidDisappear = Notification.Name("UIViewController.viewControllerDidDisappear")
}

open class NotifyingViewController: UIViewController {

    override open func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NotificationCenter.default.post(name: .viewControllerDidDisappear, object: self)
    }
}

一定有更好的方法来做到这一点?

【问题讨论】:

  • 你的意思是 iOS 13 演示文稿吗?
  • 在某些 iphone 上可以通过手势关闭呈现的视图控制器 ||这是在运行 13.0 及更高版本的设备上关闭 VC 的默认方式。
  • 是的,我会编辑原始问题

标签: ios swift uiviewcontroller


【解决方案1】:

从 iOS 13 开始,Apple 为用户引入了一种新的方式来dismiss 呈现的视图控制器,方法是将其从顶部拉下。可以通过将UIAdaptivePresentationControllerDelegate 实现到您正在呈现的UIViewController(在本例中为Presenting 控制器)来捕获此事件。然后您可以在方法presentationControllerDidDismiss 中收到有关此事件的通知。这是代码示例:-

class Presenting: UIViewController, UIAdaptivePresentationControllerDelegate {

    func someAction() {
        let presented = Presented()
        presented.presentationController?.delegate = self
        present(presented, animated: true, completion: nil)
    }

    func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
        // Only called when the sheet is dismissed by DRAGGING.
        // You'll need something extra if you call .dismiss() on the child.
        // (I found that overriding dismiss in the child and calling
        // presentationController.delegate?.presentationControllerDidDismiss
        // works well).
    }
}

注意:

  1. 此方法仅在通过从顶部滑动关闭时触发,而不是为编程dismiss(animated:,completion:) 方法触发。
  2. 您不需要任何自定义委托或Notification 观察者来获取用户通过向下滑动关闭控制器的事件,因此您可以删除它们。

【讨论】:

  • 太棒了,这行得通。我会投票,但显然我没有足够的声誉。太糟糕了,它仅适用于 iOS 13,但我想在此之前没有标准的动画解雇。谢谢!
  • 为什么presentationControllerDidDismiss 是公开的?
  • 您需要 >15 个声望才能在 SO 中投票。你是正确的,用户无法通过在 iOS13 之前滑动来在视图控制器之前关闭,所以没有必要将它用于
  • @jawadAli 谢谢,我没有注意到。双向工作。
【解决方案2】:

采用UIAdaptivePresentationControllerDelegate并实现presentationControllerDidAttemptToDismiss(iOS 13+)

extension Presenting : UIAdaptivePresentationControllerDelegate {

    func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
       presentationController.presentingViewController.presentedDidDismiss(self)
    }
}

UIPresentationController 有一个属性presentingViewController。这个名字是不言自明的。您不需要显式委托协议。

实际上调用该方法是为了能够显示一个对话框,例如在关闭控制器之前保存更改。也可以实现presentationControllerDidDismiss()

并且不要向彼此相关的控制器发布通知。这是不好的做法。

【讨论】:

  • @jawadAli 是的,该方法已经在iOS 13 中引入。在iOS 12 及更低版本中调用viewWillDisappear
  • 感谢您提供正确的解决方案!我接受了@Frankenstein 解决方案,因为它澄清了委托 + 使用 presentationControllerDidDismiss,这在我的情况下更合适!
猜你喜欢
  • 2021-11-12
  • 1970-01-01
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-11
  • 2017-07-09
  • 1970-01-01
相关资源
最近更新 更多