我的目标包括很多视图需要根据每个用户操作以模态方式呈现不同的视图。这就是我想要做的事情,以获得更清晰的视图层次结构和更好的用户体验。
- 根视图控制器以模态方式呈现第一视图控制器
- 当我点击第一视图控制器上的按钮时,第二视图控制器会以模态方式显示在其上。
- 第二个视图控制器出现后,我想解除或删除视图层次结构中的第一个。
醇>
我能这样做吗? 如果,我应该怎么做?
如果不是,解决此问题的正确方法是什么,我将在每个视图上呈现许多模态呈现的视图控制器。我想即使我想要忽略当前的观点,前一个观点仍然会在当前观点被忽略时出现。
更新:
VC1(Root)> VC 2(模态存在)> VC 3( 以模态方式呈现在VC 2上)
当我解雇VC3
时,VC2
仍然在查看记忆中。因此,我不希望在我解除VC2
后立即显示VC3
,而是希望通过从视图层次结构中删除或解除VC1
来查看VC2
。
想要:在图片中,当我解开蓝色时,我不想在我的视图记忆中看到粉红色,我想在蓝色出现后立即将其删除
这就是我想要做的事。
任何帮助?谢谢。
答案 0 :(得分:7)
所以,让我们假设您有一个类似于以下的故事板:
应该发生什么:
在第三个ViewController按钮的操作中:
@IBAction func tapped(_ sender: Any) {
presentingViewController?.presentingViewController?.dismiss(animated: true, completion: nil)
}
如您所见,通过访问当前ViewController的presentingViewController,您可以忽略视图控制器的先前层次结构:
提供此视图控制器的视图控制器。
通过实现presentingViewController?.presentingViewController?
,意味着:呈现的当前ViewController:)
看起来有点令人困惑,但很简单。
所以输出应该是这样的(我为viewControllers添加了背景颜色-as vc1:orange,vc2:black和vc3:light orange-以使其显得清晰):
修改强>
如果要求删除中间的ViewController(在本例中是第二个ViewController),dismiss(animated:completion:)会自动执行此操作:
如果你连续出现几个视图控制器,那么建立一个 堆栈的呈现视图控制器,在视图上调用此方法 堆栈中较低的控制器会解除其直接的子视图 控制器和堆栈上该子节点上方的所有视图控制器。 发生这种情况时,只有最顶层的视图在动画中被解除 时尚;任何中间视图控制器都可以从中删除 堆。最顶层的视图使用其模态转换被忽略 样式,可能与其他视图控制器使用的样式不同 在堆栈中较低。
参考你在问什么:
我认为即使我想要忽略当前的观点,前一个观点也会如此 当前的解雇时仍然会出现。
我认为这在UI上显而易见(我发现没问题),但正如dismiss
文档讨论中所提到的,第三个和第二个都将从堆栈中删除。这是正确的方法。
答案 1 :(得分:2)
您想要的是“放松的搜寻”:
https://developer.apple.com/library/archive/technotes/tn2298/_index.html
它使您可以同时关闭多个视图控制器,而不必知道堆栈中有多少个。
在VC1中,您将实现一个名为IBAction
的{{1}}。然后,在VC3的情节提要中,将完成按钮连接到unwindToRoot
对象,然后选择Exit
操作。
按下该按钮时,系统将关闭将您带回到VC1所需的所有视图控制器。
这比调用unwindToRoot
更好,因为VC3不需要了解其下的视图控制器层次结构。
答案 2 :(得分:1)
以不同的角度来看,这是我的观点,
- 根视图控制器提供第二视图控制器
- 将FirstView添加到第二个视图
- 按下按钮时关闭FirstView控制器。
醇>
第二视图控制器,
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,
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")
}
}