呈现ViewController 不工作
Posted
技术标签:
【中文标题】呈现ViewController 不工作【英文标题】:presentingViewController not working 【发布时间】:2018-07-11 16:00:42 【问题描述】:当我关闭弹出 ViewController 时,我想在呈现的 ViewController 上调用一个方法。我像这样从“MainViewController”启动弹出窗口:(在 EzPopup 库的帮助下,但我认为这不重要)
@IBAction func onStartWorkout(_ sender: UIButton)
let startWorkoutVC = storyboard!.instantiateViewController(withIdentifier: "CardContent") as! StartWorkout_ViewController
let popupVC = PopupViewController(contentController: startWorkoutVC, popupWidth: 300, popupHeight: 500)
popupVC.cornerRadius = 10
present(popupVC, animated: true)
然后当我关闭弹出窗口时,我会这样做:
func dissmissPopup()
if let presenter = presentingViewController as? MainViewController
presenter.startWorkout(index: 0, isSNR: true)
self.dismiss(animated: true, completion: nil)
但不会调用该方法。 presentingViewController 是如何工作的,为什么我对 MainViewController 的引用不起作用?
【问题讨论】:
这个dissmissPopup
方法在哪个类中?
因为 presentingViewController 为 nil
@Popmedic presentingViewController
是 UIViewController
的属性。
@rmaddy 如你所料,我在“StartWorkout_ViewController”上
@Sh_Khan 我知道它的 nil,问题是为什么它是 nil 以及如何解决这个问题?
【参考方案1】:
假设dissmissPopup
在你的StartWorkout_ViewController
类中,那么presentingViewController
将是nil
,因为你没有呈现StartWorkout_ViewController
,你正在呈现PopupViewController
。 PopupViewController
的 presentingViewController
应该是您的 MainViewController
。
根据PopupViewController
的编写方式,您应该能够通过访问parent
获得所需的内容(给您PopupViewController
,然后访问它的presentingViewController
。
func dissmissPopup()
if let presenter = parent?.presentingViewController as? MainViewController
presenter.startWorkout(index: 0, isSNR: true)
self.dismiss(animated: true, completion: nil)
现在,说了这么多,不要这样做。这是一个糟糕而脆弱的设计。您正在对StartWorkout_ViewController
进行硬编码,知道MainViewController
需要调用一些特定的方法。
正确的解决方案是定义协议和委托。然后StartWorkout_ViewController
简单地调用它的委托上的协议方法(不关心它到底是谁)。而MainViewController
将自己设置为StartWorkout_ViewController
的委托并实现协议的方法。
这种方法使StartWorkout_ViewController
无需知道是谁呈现它或如何呈现它。它消除了StartWorkout_ViewController
知道专门调用名为startWorkout
的方法的需要。它还允许其他类呈现 MainViewController
并在它被解除时执行它需要的任何操作,而无需对 MainViewController
进行进一步的硬编码更改。
以下是使用协议和委托实现此功能的粗略大纲:
StartWorkout_ViewController.swift:
protocol StartWorkoutDelegate: class
func complete() // add any necessary parameters
class StartWorkout_ViewController: UIViewController
weak var delegate: StartWorkoutDelegate?
func dissmissPopup()
delegate?.complete() // add any necessary parameters
self.dismiss(animated: true, completion: nil)
MainViewController.swift:
class MainViewController: UIViewController, StartWorkoutDelegate
@IBAction func onStartWorkout(_ sender: UIButton)
let startWorkoutVC = storyboard!.instantiateViewController(withIdentifier: "CardContent") as! StartWorkout_ViewController
startWorkoutVC.delegate = self
let popupVC = PopupViewController(contentController: startWorkoutVC, popupWidth: 300, popupHeight: 500)
popupVC.cornerRadius = 10
present(popupVC, animated: true)
func complete()
startWorkout() // add any necessary parameters
【讨论】:
感谢您的快速回答! 'parent?.presentingViewController' 的第一种方法不起作用。但我也宁愿采用第二种方式。您能否提供一个小代码示例?我是 swift 新手(来自 java),我知道协议是什么,但我不明白“从其委托调用协议方法”是什么意思。 非常感谢!我明白了。以上是关于呈现ViewController 不工作的主要内容,如果未能解决你的问题,请参考以下文章
如何在不知道新的 VC 的情况下将 ViewController 呈现在另一个之上?
UIPickerView 的 ViewController 在选择后冻结