【问题标题】:From within a view controller in a container view, how do you access the view controller containing the container?从容器视图的视图控制器中,如何访问包含容器的视图控制器?
【发布时间】:2014-02-10 21:15:07
【问题描述】:

这很难用词,但我有一个包含容器视图的视图控制器 (vc1)(我正在使用情节提要)。在该容器视图中是一个导航控制器和一个根视图控制器 (vc2)。

如何从 vc2 中访问 vc1?

或者,我如何将 vc1 传递给 vc2? (请记住,我正在使用情节提要)。

【问题讨论】:

标签: ios ipad view storyboard containers


【解决方案1】:

您可以在 Vc1 中使用 prepareForSegue 方法,因为当 ContainerViewController 成为子级时会发生嵌入转场。您可以将 self 作为 obj 传递或存储对孩子的引用以供以后使用。

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSString * segueName = segue.identifier;
    if ([segueName isEqualToString: @"embedseg"]) {
        UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController];
        Vc2 *detail=[navViewController viewControllers][0];
        Vc2.parentController=self;
    }
}

编辑:次要代码修复

【讨论】:

  • @Firula UINavigationController * navViewController = (UINavigationController *) [segue destinationViewController]; 行没有初始化任何东西,它只是一个指向已初始化控制器的指针。
  • 首先,命名故事板中将容器视图连接到其第一个视图控制器的 segue(link)。我将我的命名为“toContainer”。然后在包含容器视图的视图控制器中添加此方法 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString: @"toContainer"]) { UINavigationController *navViewController = ( UINavigationController *) [segue destinationViewController]; UIViewController *vc2 = [navViewController viewControllers][0]; } } vc2 是我想要引用的控制器。
  • 注意:destinationViewController 已经是我的容器嵌入目标 UIViewController
  • 这对我很有帮助,谢谢。一个相关的问题:为什么我的子视图控制器的 ViewDidLoad 方法会在父视图控制器之前被调用?我是不是把容器的设置搞砸了?
  • @Chucky 理解这一点,想象 Child 本质上是 Parent 的一部分(uicontrol),而父母 -(void)viewDidLoad 是不完整的,除非所有 UIElement 都已加载。因此,孩子的-(void)viewDidLoad 应该在父母之前被调用。
【解决方案2】:

要从子视图控制器中访问父视图控制器,您必须重写 didMoveToParentViewController

- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];

    //Use parent
}

在 Xcode 上 Command+单击此方法以获取更多信息:

这两个方法是公共的,供容器子类在子类之间转换时调用 控制器。如果它们被覆盖,覆盖应该确保调用超级。中的父参数 当孩子从其父母身上移除时,这两种方法都为零;否则等于新的 父视图控制器。

addChildViewController: 在添加之前会调用 [child willMoveToParentViewController:self] 孩子。但是,它不会调用 didMoveToParentViewController:。预计容器视图 控制器子类将在完成到新孩子的转换后进行此调用,或者在 在没有转换的情况下,在调用 addChildViewController: 之后立即。相似地 removeFromParentViewController:在删除之前不调用 [self willMoveToParentViewController:nil] 孩子。这也是容器子类的职责。容器子类通常会定义 通过首先调用 addChildViewController: 转换到新子项的方法,然后执行 将新子视图添加到其父视图层次结构中的转换,最后将调用 didMoveToParentViewController:.类似地,子类通常会定义一个删除子类的方法 反之,首先调用 [child willMoveToParentViewController:nil]。

【讨论】:

    【解决方案3】:

    您可以使用 Bonnie 使用的相同方法来使用委托。以下是你的做法:

    在您的 containerViews ViewController 中:

    class ContainerViewViewController: UIViewController {
       //viewDidLoad and other methods
    
       var delegate: ContainerViewControllerProtocol?
    
       @IBAction func someButtonTouched(sender: AnyObject) { 
        self.delegate?.someDelegateMethod() //call this anywhere
       }
    
    }
    
    protocol ContainerViewControllerProtocol {
        func someDelegateMethod()
    }
    

    在你的父 ViewController 中:

    class ParentViewController: UIViewController, ContainerViewControllerProtocol {
       //viewDidLoad and other methods
    
        override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            if segue.identifier == "filterEmbedSegue" {
                let containerViewViewController = segue.destinationViewController as ContainerViewViewController
    
                containerViewViewController.delegate = self
            }
        }
    
        func someDelegateMethod() {
            //do your thing
        }
    }
    

    【讨论】:

      【解决方案4】:

      将属性parentViewController 用作self.parentViewController

      【讨论】:

      • 就我而言,这不起作用,因为 self.parentViewController 为零。我在情节提要中添加了 containerView,然后将关联的视图控制器类设置为我的特定子类。我希望将 parentViewController 设置为包含容器视图的 VC,但这不是自动设置的。我不得不使用上面的 -prepareForSegue 解决方案
      • 属性是 swift 3 中的“self.parent”
      【解决方案5】:

      感谢 Bonnie 告诉我该怎么做。确实,为 segue 方法准备是要走的路。

      我只是在这里澄清一下代码和步骤。

      首先,命名故事板中将容器视图连接到其第一个视图控制器的 segue(link)。我将我的命名为“toContainer”。

      然后在包含容器视图的视图控制器中添加这个方法

      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
      {
          if ([segue.identifier isEqualToString: @"toContainer"]) {
              UINavigationController *navViewController = (UINavigationController *) [segue destinationViewController];
              UIViewController *vc2 = [navViewController viewControllers][0];
          }
      }
      

      所以 vc2 是我想要参考的控制器。

      这对我有用,如果你的第一个 viewconroller 不是导航控制器,你的方法在 prepareForSegue 中会略有不同。

      【讨论】:

      • 您本可以将我的答案标记为正确,然后将您的答案添加到 cmets 中以获得更好的说明。
      • 马克,您需要将 Firula 或 Bonnie 的答案标记为正确,然后继续编辑您的问题并将此有用信息放入问题中。
      【解决方案6】:

      1) 在 VC2 上公开一个用于传递对 VC1 的引用的属性

      //VC2.h
      #import "VC1.h"
      
      @interface VC2 : NSObject
      @property (strong, nonatomic) VC1 *parent;
      @end
      

      2) 在 VC1 上,将 segue 的标识符设置为“ToVC2”后,将 self 在您的 prepareForSegue 方法中传递给 VC2 中公开的属性。然后像这样传递引用:

      //VC1.m
      @implementation VC1 
      - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
      if([segue.identifier isEqualToString:@"ToVC2"]) {
          VC2 *vc2 = segue.destinationViewController;
          vc2.parent = self;
      }
      }
      

      【讨论】:

        【解决方案7】:

        Swift - 另一种方法是在父 UIViewController (vc1) 中创建对子/子视图 UIViewController (vc2) 的引用,并在 vc2 中创建对 vc1 的引用。在下面的 parent(vc1) viewDidLoad() 示例中分配引用。

        父 UIViewController vc1:

              class vc1: UIViewController {
        
                  @IBOutlet weak var parentLabel: UILabel!
                  var childVc2: vc2?;
        
                   overide func viewDidLoad() {
                       super.viewDidLoad();
                       // Use childViewControllers[0] without type/class verification only 
                       // when adding a single child UIViewController 
                       childVc2 = self.childViewControllers[0] as? vc2;
                       childVc2?.parentVc1 = self
                   }
              }
        

        子 UIViewController vc2:

              class vc2: UIViewCortoller {
                  var parentVc1: vc1?;
        
                  // At this point child and parent UIViewControllers are loaded and 
                  // child views can be accessed
                  override func viewWillAppear(_ animated: Bool) {
                     parentVc1?.parentLabel.text = "Parent label can be edited from child";
                  }
              } 
        

        在 Storyboard 中,记得在 Identity Inspector 中将父 UIViewContoller 类设置为 vc1,将子 UIViewContoller 类设置为 vc2。 Ctrl+从 vc1 UIViewController 中的 Container View 拖到 vc2 UIViewController 并选择 Embed。

        【讨论】:

          猜你喜欢
          • 2013-03-20
          • 1970-01-01
          • 1970-01-01
          • 2018-03-24
          • 2017-12-27
          • 2017-09-17
          • 2016-07-22
          • 2012-10-28
          • 1970-01-01
          相关资源
          最近更新 更多