拒绝提出的视图控制器

我有一个理论上的问题。 现在,我正在阅读苹果的ViewController指南。

他们写:

当需要closures一个呈现的视图控制器时,首选的方法是让呈现视图控制器closures它。 换句话说,只要有可能,呈现视图控制器的视图控制器也应该负责解除视图控制器。 虽然有几种技术用于通知呈现视图控制器它的呈现的视图控制器应该被解散,但是优选的技术是委派。

但我不能解释,为什么我必须在提出的VC中创build一个协议,并添加委托variables,创build委托方法提出VC退出提出的VC,而不是一个简单的调用呈现的视图控制器方法

[self dismissViewControllerAnimated:NO completion:nil]

为什么第一个select更好? 为什么苹果推荐它?

我认为苹果在这里稍微掩盖了他们背后的一块API。

  [self dismissViewControllerAnimated:NO completion:nil] 

实际上是一个小提琴。 虽然你可以 – 合法地 – 在所提供的视图控制器上调用它,它所做的只是将消息转发给呈现视图控制器。 如果你想做任何事情,只要解雇VC,你就需要知道这一点,你需要像委托方法一样对待它 – 因为这几乎就是这样,一个有点不灵活的委托方法。

也许他们已经遇到了一些不太了解如何放在一起的人的糟糕的代码,因此他们谨慎。

但是,当然,如果你只需要解雇这个东西,那就继续吧。

我自己的做法是妥协,至less它让我想起发生了什么事情:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil] 

如果使用swift3.0及更高版本…

让rootViewController:UIViewController =(UIApplication.shared.keyWindow?.rootViewController)!

  if (rootViewController.presentedViewController != nil) { rootViewController.dismiss(animated: true, completion: { //completion block. }) } 

这是视图控制器的可重用性。

你的视图控制器不应该关心它是作为一个模式呈现,推在导航控制器,或其他任何东西。 如果你的视图控制器自行解散,那么你就假设它是以模态方式呈现的。 您将无法将视图控制器推到导航控制器上。

通过实现一个协议,你让父视图控制器决定如何显示/推送和解散/popup。

更新了Swift 3

我来这里只是想解雇当前(呈现)的视图控制器。 任何来这里的人都有同样的目的。

导航控制器

如果你使用的是导航控制器,那么这很容易。

回到上一个视图控制器:

 // Swift self.navigationController?.popViewController(animated: true) // Objective-C [self.navigationController popViewControllerAnimated:YES]; 

回到根视图控制器:

 // Swift self.navigationController?.popToRootViewController(animated: true) // Objective-C [self.navigationController popToRootViewControllerAnimated:YES]; 

(感谢Objective-C的这个答案 )

模态视图控制器

当视图控制器以模态方式呈现时,您可以通过调用(从第二个视图控制器)解除视图控制器

 // Swift self.dismiss(animated: true, completion: nil) // Objective-C [self dismissViewControllerAnimated:YES completion:nil]; 

该文件说,

呈现视图控制器负责解除其呈现的视图控制器。 如果您在所提供的视图控制器本身上调用此方法,UIKit会要求呈现视图控制器来处理解除。

所以它适用于呈现的视图控制器自己调用它。 这是一个完整的例子。

代表

OP的问题是关于使用代表驳回观点的复杂性。

  • 这个Objective-C的答案进入了很多。
  • 这是一个Swift示例。

到目前为止,我不需要使用委托,因为我通常有一个导航控制器或模式视图控制器,但如果我确实需要在将来使用委托模式 ,我将添加更新。

根据我的经验,当你需要从任何你想要的ViewController中解散它,并为每个视图控制器执行不同的任务时,它就派上用场了。 任何采用该协议的viewController都可以用自己的方式解除视图。 (iPad或iPhone,或从不同的观点解散时传递不同的数据,解雇时调用不同的方法等)。

编辑:

所以,为了澄清,如果你想要做的就是解散视图,我不需要设置委托协议。 如果您从不同的呈现视图控制器中解散它之后需要做不同的事情那么这将是使用委托的最佳方式。

尝试这个:

 [self dismissViewControllerAnimated:true completion:nil]; 

来自View Controller编程指南 “View Controller如何呈现其他视图控制器”。

呈现的视图控制器链中的每个视图控制器具有指向链中围绕它的其他对象的指针。 换句话说,呈现另一个视图控制器的呈现视图控制器在其呈现视图控制器和呈现视图控制器属性中都具有有效对象。 您可以根据需要使用这些关系追踪视图控制器链。 例如,如果用户取消当前操作,则可以通过closures第一个呈现的视图控制器来删除链中的所有对象。 closures视图控制器不仅closures了视图控制器,而且还closures了视图控制器。

所以一方面它是一个很好的平衡devise,很好的去耦合等等。但另一方面,这是非常实用的,因为你可以很快回到导航的某个点。

虽然,我个人宁愿使用展开segues,而不是尝试向后遍历呈现的视图控制器树,这正是苹果在本章中引用的引用来自的地方。

有一点是这是一个很好的编码方法。 它满足了许多OOP原则,例如,SRP,关注的分离等。

所以,视图控制器呈现的视图应该是一个解雇它的人。

比如,一个房租公司应该有权收回房租。

这是很多的胡扯。 在需要的时候委派是很好的,但是如果它使得代码更加复杂 – 而且确实如此 – 那么就需要有一个原因。

我相信苹果有其原因。 但是,除非有真正的理由否则,否则只是让提出的风险投资者去解决这个问题,这是更加清楚和简洁的,今天这里没有人提出我能看到的。

协议在需要的时候是非常好的,但是面向对象的devise永远不会让模块彼此之间进行不必要的通信。

目标C的共同开发者汤姆·洛夫(Tom Love)曾经评论过Objective C是“优雅”,“小巧”,“清晰”和“明确定义”(与C ++相比)。 容易他说。 授权是一个有用的function,似乎被“过度使用”,虽然我喜欢使用这种语言,但是我害怕使用不必要的语法来使事情变得复杂得多。

Swift 3.0 //closures视图控制器在swift中

 self.navigationController?.popViewController(animated: true) dismiss(animated: true, completion: nil) 

如果你正在使用模态使用查看解雇。

 [self dismissViewControllerAnimated:NO completion:nil]; 

除了迈克尔·恩里克斯的回答之外,我还可以想到另外一个原因,为什么这可能是保护自己不受未确定状态的好办法:

假设ViewControllerA以模态方式呈现ViewControllerB。 但是,由于您可能没有编写ViewControllerA的代码,因此您不了解ViewControllerA的生命周期。 在呈现您的视图控制器ViewControllerB之后,它可能会消失5秒(说)。

在这种情况下,如果你只是简单地使用ViewControllerB中的dismissViewController来解除它自己,那么你最终会处于一个未定义的状态 – 可能不是崩溃或黑屏,而是一个未定义的状态。

相反,如果您使用委托模式,您将意识到ViewControllerB的状态,您可以编写一个像我所描述的情况。

迅速

 let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)! if (rootViewController.presentedViewController != nil) { rootViewController.dismiss(animated: true, completion: { //completion block. }) }