【问题标题】:Access modal view controller parent访问模态视图控制器父级
【发布时间】:2011-07-18 15:16:01
【问题描述】:

我正在模态地展示一个 ViewController。 如何访问父视图控制器?

我的架构是 TabBarController=>VC1=>VC2=>VC3=>MVC1,我想从 MVC1 到达 VC3。

在 VC3 中,我有这个代码:

- (void) editAd{
    AskPasswordViewController *modalViewController = [[AskPasswordViewController alloc] initWithNibName:@"AskPasswordView" bundle:nil];

    NSLog(@"modalparent class=%@", [[modalViewController parentViewController] class]);

    [self presentModalViewController:modalViewController animated:YES];
    [modalViewController release];
}

我在 MVC1 中试过这个:

- (void) sendRequest {
    NSLog(@"classe : %@",[[self parentViewController] class] );
}

但它会返回我的 TabBarViewController...

【问题讨论】:

    标签: iphone ios


    【解决方案1】:

    您可以通过调用访问父级:

    self.presentingViewController
    

    根据苹果文档:

    呈现此视图控制器(或其 最远的祖先。)

    【讨论】:

    • 虽然其他 cmets 在他们的时代是正确的,但我认为这是使用故事板的方式(尤其是从 iOS 7 开始)
    • 仅供参考,这在 viewDidLoad 中将为零
    【解决方案2】:

    我会做这样的事情的方式是简单地创建一个委托。在AskPasswordViewController的头部,放

    id delegate;
    

    @property (nonatomic, assign) id delegate;
    

    在实现文件中综合它。然后在你分配/初始化模态控制器之后,在你展示它之前,设置modalViewController.delegate = self;。然后在模态控制器中,您可以调用self.delegate 从呈现它的视图控制器中获取信息。我希望这会有所帮助

    【讨论】:

    • 谢谢。这就是我最终所做的。但我想了解为什么父视图控制器是标签栏。看起来真的很奇怪,我害怕在某个地方做错了什么。
    • 我不完全确定为什么,但我的理论是,由于您正在呈现一个模态视图,它不一定是呈现它的视图控制器的子视图,而是它的一部分。因此,它的父级是将其作为扩展呈现的视图的父级。它似乎在这方面有不同的行为,而不是通过导航控制器推送视图
    • 它也对我有用。但我不得不让类“parentviewcontroller”的代表。我想访问“parentviewcontroller”的uitabbar。
    • 值得指出的是,这是 Apple 官方推荐的解决此问题的方法,详见此处的“呈现“视图控制器并选择过渡样式”部分:developer.apple.com/library/ios/#featuredarticles/…
    【解决方案3】:

    您总是可以通过像这样调用 parentViewController 来进一步返回:

    self.parentViewController.parentViewController .... 以此类推,直到找到正确的。

    【讨论】:

    • 我有一个tabbar,它展示了navigationController,它推送了一些viewcontroller,它展示了烦人的viewController。
    • 在你的问题中给我们一个反馈,就像告诉我们你 modalviewcontroller archtecture vc1 -> vc2 -> nvc -> tbvc 然后告诉我们你想从哪里到哪里去。
    • 要打印实际的类名,请使用:NSLog(@"clase : %@",NSStringFromClass[[self parentViewController] class]) );
    • 从 MVC1 调用 self.parentViewController 应该没问题。它将达到 VC3。
    【解决方案4】:

    Vibhor Goyal 的补充 - 有时,self.presentingViewController 注册为 NavigationController。因此尝试:

    if let vc = self.presentingViewController.childViewControllers.last as? YourViewController {
    // do stuff here
    }
    

    【讨论】:

      【解决方案5】:

      在这里,我想出了从任何地方导航到根目录的通用方法。

      1. 您使用该类创建一个新的 Class 文件,以便可以从项目中的任何位置访问它:

        import UIKit
        
        class SharedControllers
        {
            static func navigateToRoot(viewController: UIViewController)
            {
                var nc = viewController.navigationController
        
                // If this is a normal view with NavigationController, then we just pop to root.
                if nc != nil
                {
                    nc?.popToRootViewControllerAnimated(true)
                    return
                }
        
                // Most likely we are in Modal view, so we will need to search for a view with NavigationController.
                let vc = viewController.presentingViewController
        
                if nc == nil
                {
                    nc = viewController.presentingViewController?.navigationController
                }
        
                if nc == nil
                {
                    nc = viewController.parentViewController?.navigationController
                }
        
                if vc is UINavigationController && nc == nil
                {
                    nc = vc as? UINavigationController
                }
        
                if nc != nil
                {
                    viewController.dismissViewControllerAnimated(false, completion:
                        {
                            nc?.popToRootViewControllerAnimated(true)
                    })
                }
            }
        }
        
      2. 在项目中的任何地方使用:

        {
            ...
            SharedControllers.navigateToRoot(self)
            ...
        }
        

      【讨论】:

      • 这是不好的做法!
      【解决方案6】:
      //You have to get the root, iterate through the root's ViewControllers and then ask for the ParentViewController.
          UINavigationController ​*root = (UINavigationController*​)[[(AppDelegate*) [[UIApplication sharedApplication]delegate] window] rootViewController];
                 for (UIViewController *VC in root.viewControllers) {
                     if([VC isKindOfClass:[YourParentViewController class]]){
                         YourParentViewController*  parent = (YourParentViewController*)VC;
                         [parent callMethod]; // your code here
                         [self dismissViewControllerAnimated:YES completion:nil];
                     }
                 }
      

      【讨论】:

        【解决方案7】:

        如果presentingViewController 给了你意想不到的结果,而你又不想摆弄它,那就这样做吧:

        class MyViewController: UIViewController {
        
            private weak var presenter: UIViewController?
        
            init(presenter: UIViewController) {
                self.presenter = presenter
                super.init(nibName: nil, bundle: nil)
                ...
            }
            
            ...
        }
        

        【讨论】:

          猜你喜欢
          • 2012-10-26
          • 2015-07-14
          • 1970-01-01
          • 2018-05-11
          • 1970-01-01
          • 2012-10-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多