解雇呈现的视图控制器

时间:2013-01-31 23:14:22

标签: iphone ios objective-c cocoa-touch uiviewcontroller

我有一个理论问题。现在我正在阅读Apple的ViewController指南。

他们写道:

  

当解雇一个呈现的视图控制器时,   首选方法是让呈现视图控制器解除   它。换句话说,只要有可能,就是相同的视图控制器   提出视图控制器也应该承担责任   解雇它。虽然有几种技术可以通知   呈现视图控制器,其呈现的视图控制器应该   被驳回,首选技术是授权。

但我无法解释,为什么我必须在呈现的VC中创建协议并添加委托变量,创建委托方法以呈现VC以解除呈现的VC,而不是在呈现中的简单调用视图控制器方法

[self dismissViewControllerAnimated:NO completion:nil]

为什么首选更好?为什么Apple推荐它?

14 个答案:

答案 0 :(得分:107)

我认为苹果公司正在为这一潜在的大量API提供支持。

  [self dismissViewControllerAnimated:NO completion:nil]

实际上有点小提琴。虽然您可以 - 合法地 - 在呈现的视图控制器上调用它,但它只是将消息转发到呈现视图控制器。如果你想做除了忽略VC之外的任何事情,你需要知道这一点,你需要像委托方法一样对待它 - 因为它几乎就是它,一个有点不灵活的烘焙委托方法。

也许他们遇到了大量不良代码的人并不真正理解这是如何组合在一起的,因此他们要谨慎。

但是,当然,如果您需要做的就是解雇这个问题,请继续。

我自己的方法是妥协,至少它让我想起发生了什么:

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

[夫特]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

答案 1 :(得分:47)

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

您的视图控制器不应该关心它是作为模态呈现,推送到导航控制器上还是其他任何内容。如果你的视图控制器自我解散,那么你假设它是以模态呈现的。您将无法将该视图控制器推送到导航控制器上。

通过实施协议,您可以让父视图控制器决定如何呈现/推送和解除/弹出它。

答案 2 :(得分:43)

更新了Swift 3

我来到这里只是想解雇当前(呈现)的View Controller。我为那些来到这里的人做出了同样的回答。

导航控制器

如果您使用的是导航控制器,则非常容易。

返回上一个视图控制器:

// 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的this answer。)

模态视图控制器

当以模态方式呈现视图控制器时,您可以通过调用

将其关闭(从第二个视图控制器)
// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

documentation说,

  

呈现视图控制器负责解除视图   它呈现的控制器。如果在显示的视图上调用此方法   控制器本身,UIKit要求呈现视图控制器处理   解雇。

因此它适用于呈现的视图控制器自己调用它。 Here就是一个完整的例子。

代表

OP的问题是关于使用委托解雇视图的复杂性。

到目前为止,我不需要使用委托,因为我通常有导航控制器或模态视图控制器,但如果我将来需要使用the delegate pattern,我将添加更新。

答案 3 :(得分:6)

根据我的经验,当您需要从 任何 所需的ViewController中解除它并为每个取消它的viewcontroller执行不同的任务时,它会派上用场。任何采用该协议的viewController都可以以自己的方式解除视图。 (ipad vs iphone,或者从不同的视图中传递不同的数据,在解雇时调用不同的方法等等。)

编辑:

因此,澄清一下,如果你想做的就是解雇视图,我认为没有必要设置委托协议。如果您需要在 后执行不同的操作 ,则将其从不同的呈现视图控制器中删除,这将是您使用该委托的最佳方式。

答案 4 :(得分:6)

试试这个:

[self dismissViewControllerAnimated:true completion:nil];

答案 5 :(得分:2)

引用视图Controller Programming Guide,“视图控制器如何呈现其他视图控制器”。

  

呈现的视图控制器链中的每个视图控制器都具有   指向链中围绕它的其他对象的指针。其他   单词,呈现另一个视图的呈现视图控制器   controller在presentViewController中都有有效的对象   presentsViewController属性。您可以使用这些关系   根据需要跟踪视图控制器链。 例如,如果   用户取消当前操作,您可以删除所有对象   通过解雇第一个呈现的视图控制器链。   关闭视图控制器不仅会解除视图控制器   还有它呈现的任何视图控制器。

因此,它一方面可以实现良好的平衡设计,良好的分离效果等......但另一方面它非常实用,因为您可以快速回到导航中的某个点。

虽然,我个人宁愿使用展开segues 而不是试图向后遍历呈现视图控制器树,这正是Apple在本章中所说的引用是从。

答案 6 :(得分:2)

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

因此,呈现视图的视图控制器应该是解雇它的视图控制器。

就像,一个租房子的房地产公司应该是收回房屋的权力。

答案 7 :(得分:2)

Swift 3.0 //在swift

中关闭View Controller
self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

答案 8 :(得分:1)

除了Michael Enriquez的回答之外,我还能想到另一个原因,为什么这可能是保护自己免于未定状态的好方法:

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

在这种情况下,如果您只是使用ViewControllerB中的dismissViewController来解除自身,那么您最终将处于未定义状态 - 可能不是崩溃或黑屏,而是从您的角度看未定义的状态

如果您正在使用委托模式,那么您将了解ViewControllerB的状态,并且可以为我描述的情况编写一个案例。

答案 9 :(得分:0)

如果您正在使用模态使用视图解除。

[self dismissViewControllerAnimated:NO completion:nil];

答案 10 :(得分:0)

这是很多胡扯。授权在需要时很好,但如果它使代码更复杂 - 而且确实如此 - 则需要有一个理由。

我确信Apple有其原因。但更简洁,更简洁的是,只要让所呈现的VC做出解雇,除非有其它原因,否则今天没有人提出我能看到的。

协议在需要时非常出色,但面向对象的设计绝不是让模块彼此之间不必要地进行通信。

汤姆·洛夫(目标C的共同开发者)曾评论说,目标C是“优雅的”,“#34;小","清脆"和#34;定义良好的" (与C ++比较时)。他很容易说。委托是一个有用的功能,似乎已被过度使用"只是因为",虽然我喜欢使用该语言,但我害怕感谢使用不必要的语法使事情比他们更复杂必须是。

答案 11 :(得分:0)

夫特

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

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

答案 12 :(得分:0)

您可以关闭超级视图窗口

self.view.superview?.window?.close()

答案 13 :(得分:0)

我喜欢这个:

        (viewController.navigationController?.presentingViewController
            ?? viewController.presentingViewController
            ?? viewController).dismiss(animated: true)