Iphone 一次关闭多模态视图控制器?

Iphone 一次关闭多模态视图控制器?,iphone,uiviewcontroller,modal-dialog,dismiss,Iphone,Uiviewcontroller,Modal Dialog,Dismiss,所以有一个包含三个视图控制器的堆栈,其中a是根,B是第一个模态视图控制器,C是第三个模态vc。我想马上从C转到A。我试过了。它确实有效,但不正确。也就是说,当关闭最后一个视图控制器时,它将在显示第一个视图控制器之前快速显示第二个视图控制器。我要寻找的是一种从第三个vc到第一个的方法,在一个漂亮的动画中,不需要注意第二个视图。非常感谢您在这方面提供的任何帮助。您想要使用的是 popToRootViewControllerAnimated:。它可以让您访问根控制器,而不显示所有中间控制器。请确保只调

所以有一个包含三个视图控制器的堆栈,其中a是根,B是第一个模态视图控制器,C是第三个模态vc。我想马上从C转到A。我试过了。它确实有效,但不正确。也就是说,当关闭最后一个视图控制器时,它将在显示第一个视图控制器之前快速显示第二个视图控制器。我要寻找的是一种从第三个vc到第一个的方法,在一个漂亮的动画中,不需要注意第二个视图。非常感谢您在这方面提供的任何帮助。

您想要使用的是
popToRootViewControllerAnimated:
。它可以让您访问根控制器,而不显示所有中间控制器。

请确保只调用一次dismissModalViewControllerAnimated:

我发现,要求取消每个堆叠的模态视图控制器将导致它们都设置动画

你有:
A=modal>B=modal>C

您应该只调用
[myViewControllerA DismissModalViewController激活:是]


如果您使用
[myViewControllerB dismissModalViewControllerAnimated:YES]
,它将关闭C,而不是B。在正常(无堆栈)使用中,它将关闭B(由于响应者链将消息冒泡到A)。在您描述的堆叠场景中,B是父视图控制器,优先于模态视图控制器。

您可以在rootViewController中关闭这些ModalViewController

    UIViewController *viewController = yourRootViewController;

    NSMutableArray *array = [NSMutableArray array];
    while (viewController.modalViewController) {
        [array addObject:viewController];
        viewController = viewController.modalViewController;
    }

    for (int i = 0; i < array.count; i++) {
        UIViewController *viewController = array[array.count-1-i];
        [viewController dismissModalViewControllerAnimated:NO];
    }
UIViewController*viewController=yourRootViewController;
NSMutableArray*数组=[NSMutableArray];
while(viewController.modalViewController){
[array addObject:viewController];
viewController=viewController.modalViewController;
}
对于(int i=0;i
虽然被接受的答案确实对我有用,但它现在可能已经过时了,留下了一个看起来很奇怪的动画,最上面的模态会立即消失,动画会出现在后面的modalview上。我尝试了很多方法来避免这种情况,最后不得不使用一些技巧来使它看起来很漂亮。 注:(仅在iOS8+中测试,但应在iOS7+中工作)

基本上,viewControllerA创建一个
UINavigationController
,其中
viewControllerB
作为根视图,并以模式显示它

// ViewControllerA.m
- (void)presentViewB {
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerB];

    navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
    [self presentViewController:navigationController animated:YES completion:nil];
}
现在,在
viewControllerB
中,我们将以相同的方式呈现
viewControllerC
,但呈现之后,我们将在
viewControllerB
的导航控制器的视图层上放置
viewControllerC
的快照。然后,当解雇期间
viewControllerC
消失时,我们将看不到更改,动画将看起来很漂亮

//ViewControllerB.m
- (void)presentViewC {
    ViewControllerC *viewControllerC = [[ViewControllerC alloc] init];

    // Custom presenter method to handle setting up dismiss and snapshotting 
    // I use this in a menu that can present many VC's so I centralized this part.
    [self presentViewControllerForModalDismissal:viewControllerC];
}
下面是我的助手函数,用于显示视图和处理解雇。 需要注意的是,我使用Purelayout添加自动布局约束。您可以修改此选项以手动添加它们,或者在

现在,我们只需要确保在ViewControllerC.h中将dismissBlock定义为一个属性(显然,您可以使用委托方法或其他同样令人兴奋的设计模式来替换整个部分,重要的部分是在viewControllerB级别处理dismission)


希望这有帮助,快乐编程:)

对于任何想找工作的人,您可以这样做:

  • 用窗口的快照覆盖所有内容
  • 在没有动画的情况下关闭两个视图控制器
  • 在另一个视图控制器中显示快照的副本,而不显示动画
  • 删除覆盖窗口的快照
  • 使用动画关闭快照视图控制器
  • 代码如下:

    let window = UIApplication.shared.keyWindow!
    let snapshot = window.snapshotView(afterScreenUpdates: false)!
    window.addSubview(snapshot)
    
    let baseViewController = self.presentingViewController!.presentingViewController!
    
    baseViewController.dismiss(animated: false) {
        let snapshotCopy = snapshot.snapshotView(afterScreenUpdates: false)!
        let snapshotViewController = UIViewController()
        snapshotViewController.view.addSubview(snapshotCopy)
    
        baseViewController.present(snapshotViewController, animated: false) {
            snapshot.removeFromSuperview()
            baseViewController.dismiss(animated: true, completion: nil)
        }
    }
    

    您可以递归查找presentingViewController以访问根目录:

    extension UIViewController {
        
        private func _rootPresentingViewController(_ vc:UIViewController, depth:Int) -> UIViewController? {
            guard let parentPresenter = vc.presentingViewController else {
                return vc
            }
            if depth > 20 {
                return nil
            }
            return _rootPresentingViewController(parentPresenter, depth: depth + 1)
        }
        
        @objc
        func rootPresentingViewController() -> UIViewController? {
            return _rootPresentingViewController(self, depth: 0)
        }
        
    }
    

    这里有一个简单的方法,你可以“解雇回家”:


    如果a是
    UINavigationController
    的根,那么这是一个很好的解决方案。我刚刚醒来,所以我没听清楚。现在我使用:[[self-parentViewController]parentViewController]DismissModalViewController激活:是];这将使用根视图控制器。然而,它仍然显示了第二个vc的一个breif秒。哦,我应该说我使用了实用程序模板,第二个vc是反向视图。第三个是从反面实例化的模式vc。注意:在iOS5中,它改为“presentingViewController”并投票支持一个工作解决方案,但这确实是疯狂的(与它的优点相比),但实际上并没有一个好的工作解决方案是简单且看起来不错的。我很沮丧,苹果公司还没有一个好的方法来处理这个问题。希望在今年秋天发布新版本。绝对正确。我采用了另一种方法,一个接一个地取消ViewController(这不是问题的解决方案,但它可以工作,也没有那么难看)取消更多模态视图控制器的更通用的方法
    let window = UIApplication.shared.keyWindow!
    let snapshot = window.snapshotView(afterScreenUpdates: false)!
    window.addSubview(snapshot)
    
    let baseViewController = self.presentingViewController!.presentingViewController!
    
    baseViewController.dismiss(animated: false) {
        let snapshotCopy = snapshot.snapshotView(afterScreenUpdates: false)!
        let snapshotViewController = UIViewController()
        snapshotViewController.view.addSubview(snapshotCopy)
    
        baseViewController.present(snapshotViewController, animated: false) {
            snapshot.removeFromSuperview()
            baseViewController.dismiss(animated: true, completion: nil)
        }
    }
    
    extension UIViewController {
        
        private func _rootPresentingViewController(_ vc:UIViewController, depth:Int) -> UIViewController? {
            guard let parentPresenter = vc.presentingViewController else {
                return vc
            }
            if depth > 20 {
                return nil
            }
            return _rootPresentingViewController(parentPresenter, depth: depth + 1)
        }
        
        @objc
        func rootPresentingViewController() -> UIViewController? {
            return _rootPresentingViewController(self, depth: 0)
        }
        
    }
    
        var vc: UIViewController = self
        while vc.presentingViewController != nil {
            vc = vc.presentingViewController!
        }
        vc.dismiss(animated: true, completion: nil)