[英]Dismiss or remove previous modally presented view controller as soon as the next one appear modally
My target include a lot view need to present different view modally base on each user action. 我的目标包括很多视图需要根据每个用户操作以模态方式呈现不同的视图。 Here what I want to do to get cleaner view hierarchy and better user experience. 这就是我想要做的更清晰的视图层次结构和更好的用户体验。
- Root View Controller present First View Controller modally Root View Controller以模态方式呈现First View Controller
- When I clicked button on the First View Controller, then the Second View Controller appear modally over it. 当我单击第一视图控制器上的按钮时,第二视图控制器以模态方式显示在它上面。
- As soon as the Second View Controller did appear, I want to dismiss or remove the first one from view hierarchy. 第二个视图控制器出现后,我想从视图层次结构中解除或删除第一个视图控制器。
Can I do that? 我能这样做吗? If so , how should i do it? 如果是这样 ,我该怎么办?
If not , what is the right way to solve this out cause I will present many modally presented view controllers over each view. 如果没有 ,解决这个问题的正确方法是什么,我将在每个视图上呈现许多模态呈现的视图控制器。 I think even if I want to dismiss current view, the previous one will still remain appear when current one dismiss. 我想即使我想要忽略当前的观点,前一个观点仍然会在当前观点被忽略时出现。
UPDATE : 更新:
VC1 (Root) > VC 2 (which was present modally) > VC 3 (which was present modally over VC 2) VC1(Root)> VC 2(模态存在)> VC 3( 在VC 2上以模态存在)
When i dismiss VC3
, the VC2
is still on view memory. 当我关闭VC3
, VC2
仍然在视图内存上。 So, I don't want to appear VC2
as soon as I dismiss VC3
and instead I want to see VC1
by removing or dismissing VC2
from view hierarchy. 因此,我不想在我解除VC3
立即出现VC2
,而是希望通过从视图层次结构中删除或解除VC2
来查看VC1
。
WANT : At the image, when I dismiss the blue,I don't want see the pink in my view memory and I want to remove it as soon as the blue one appear. 想要 :在图像中,当我解雇蓝色时,我不希望在我的视图记忆中看到粉红色,我想在蓝色出现时立即将其删除。
That's what i want to do. 这就是我想要做的。
Any Help?Thanks. 任何帮助?谢谢。
So, let's assume that you have a storyboard similar to: 所以,我们假设你有一个类似于的故事板:
What should happens is: 应该发生的是:
In the third ViewController button's action: 在第三个ViewController按钮的动作中:
@IBAction func tapped(_ sender: Any) {
presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
As you can see, by accessing the presentingViewController of the current ViewController, you can dismiss the previous hierarchy of the view controllers: 正如你所看到的,通过访问presentingViewController当前视图控制器,你可以关闭该视图控制器以前的层次结构:
The view controller that presented this view controller. 提供此视图控制器的视图控制器。
By implementing presentingViewController?.presentingViewController?
通过实现presentingViewController?.presentingViewController?
that means that: the presented of the presented current ViewController :) 这意味着:呈现当前的ViewController :)
It might seem a little bit confusing, but it is pretty simple. 这看起来有点混乱,但很简单。
So the output should be like (I added background colors to the viewControllers -as vc1: orange, vc2: black and vc3: light orange- to make it appears clearly): 所以输出应该是这样的(我为viewControllers添加了背景颜色-as vc1:orange,vc2:black和vc3:light orange-以使其显得清晰):
EDIT: 编辑:
If you are asking to remove the ViewController(s) in the middle (which in this example the second ViewController), dismiss(animated:completion:) does this automatically: 如果要求在中间删除ViewController(在本例中为第二个ViewController),则dismiss(animated:completion :)会自动执行此操作:
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. 如果连续呈现多个视图控制器,从而构建一堆呈现的视图控制器,则在堆栈中较低的视图控制器上调用此方法会解除其直接子视图控制器以及堆栈上该子视图上方的所有视图控制器。 When this happens, only the top-most view is dismissed in an animated fashion; 发生这种情况时,只有最顶层的视图以动画方式被删除; any intermediate view controllers are simply removed from the stack. 任何中间视图控制器都可以从堆栈中删除。 The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack. 最顶层的视图使用其模态过渡样式被忽略,这可能与堆栈中较低的其他视图控制器使用的样式不同。
Referring to what are you asking: 参考你在问什么:
I think even if I want to dismiss current view, the previous one will still remain appear when current one dismiss. 我想即使我想要忽略当前的观点,前一个观点仍然会在当前观点被忽略时出现。
I think that appears clearly on the UI (and I find it ok), but as mentioned in the dismiss
documentation discussion, both the third and the second will be removed from the stack. 我认为在UI上显而易见(我发现它没问题),但正如在dismiss
文档讨论中所提到的,第三个和第二个都将从堆栈中删除。 That's the right way. 那是正确的方法。
What you want is an "unwind segue": 你想要的是一个“放松segue”:
https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html#//apple_ref/doc/uid/TP40007457-CH15-SW8 https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html#//apple_ref/doc/uid/TP40007457-CH15-SW8
https://developer.apple.com/library/archive/technotes/tn2298/_index.html https://developer.apple.com/library/archive/technotes/tn2298/_index.html
It allows you to dismiss multiple view controllers at the same time, without having to know how many there are in the stack. 它允许您同时关闭多个视图控制器,而无需知道堆栈中有多少个。
In VC1 you would implement an IBAction
called (for instance) unwindToRoot
. 在VC1中,您将实现一个名为(例如) unwindToRoot
的IBAction
。 Then in the storyboard for VC3, you wire up your Done button to the Exit
object and choose the unwindToRoot
action. 然后在VC3的故事板中,将“完成”按钮连接到“ Exit
对象,然后选择unwindToRoot
操作。
When that button is pressed, the system will dismiss all the view controllers it needs to bring you back to VC1. 按下该按钮后,系统将关闭所需的所有视图控制器,以便将您带回VC1。
This is better than calling presentingViewController?.presentingViewController?.dismiss()
, because VC3 doesn't need to know anything about the view controller hierarchy underneath it. 这比调用presentingViewController?.presentingViewController?.dismiss()
更好,因为VC3不需要知道它下面的视图控制器层次结构。
Here is my opinion in different perspective, 以下是我对不同角度的看法,
- Root View Controller present Second View Controller Root View Controller提供第二视图控制器
- Add FirstView onto Second View 将FirstView添加到第二个视图
- Dismiss FirstView Controller when button pressed. 按下按钮时关闭FirstView控制器。
Second View Controller, 第二视图控制器,
class ViewController: UIViewController, FirstViewControllerProtocol {
weak var firstViewController: FirstViewController?
override func viewDidLoad() {
super.viewDidLoad()
print("Not initiated: \(firstViewController)")
firstViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "FirstViewController") as? FirstViewController
addChildViewController(firstVC!)
firstViewController?.delegate = self
view.addSubview((firstViewController?.view)!)
print("Initiated: \(firstViewController)")
}
func dismiss() {
firstViewController?.view.removeFromSuperview()
firstViewController?.removeFromParentViewController()
}
}
FirstViewController, FirstViewController,
protocol FirstViewControllerProtocol {
// Use protocol/delegate to communicate within two view controllers
func dismiss()
}
class FirstViewController: UIViewController {
var delegate: FirstViewControllerProtocol?
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func dismiss(_ sender: Any) {
delegate?.dismiss()
}
deinit {
print("BYE")
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.