使用Interface Builder时查看控制器遏制

时间:2014-06-28 18:03:20

标签: ios objective-c ios7 uiview uiviewcontroller

我尝试使用Interface Builder定义一系列容器视图控制器(可能是我的第一个错误)。在故事板中,我创建了顶视图控制器,添加了3个容器视图,自动将每个子视图控制器添加到故事板。我为每个容器视图添加了一个插座,并且能够通过隐藏/显示容器视图成功地操纵子视图。真的没什么代码可言,只是:

-(IBAction) button1Pushed:(id)sender
{
     containerView2.hidden = true;
     containerView1.hidden = false;
}

虽然可行,但我需要更新每次展示的内容。 viewWillAppear(和相关函数)仅在初始创建时触发子视图控制器,而不是在隐藏/显示容器时触发。我想我可以添加类似的内容:

    [childVC1 updateContent];
    containerView1.hidden = false;

但我希望我可以依赖viewWillAppear(及相关函数)。我尝试了一些成功有限的事情,并提出了几个问题:

  1. 我理解Apple编程指南中用于手动创建容器的示例:
  2.  [self addChildViewController:content];                 // 1
     [self.view addSubview:self.currentClientView];
     [content didMoveToParentViewController:self];          // 3
    

    但使用IB时如何应用?在该编程指南中没有提到IB。 IB必须调用addChildViewController,因为我可以使用[self childViewControllers]找到所有容器VC。但由于viewWillAppear只发生在创建上,这是否意味着IB还没有继续添加视图?

    所以问题1是:通过Interface Builder添加容器视图时,IB处理的示例代码有多少,我需要实现多少?

    1. 作为实验,我将此代码添加到父级的viewDidLoad中:
    2. for ( UIViewController *vc in [self childViewControllers])
      {
          [self.view addSubview:vc.view];
          [vc didMoveToParentViewController:self];
      }
      

      这导致每个子视图都在屏幕的左上角一次显示在彼此的顶部。它不再尊重IB布局,并且不出所料,不再尊重显示/隐藏containerView。我可以用

      来控制它们
       vc.view.hidden = true;
      

      但他们已经转移到某个默认位置。我可以手动重置它们的坐标,但首先使用IB的原因之一是避免通过代码进行屏幕定位。

      问题#2是:在IB中添加容器视图时,如何在仍然遵循IB布局的同时管理显示子项?通过操纵容器视图的出口?通过操纵子视图控制器(通过[self childViewControllers]找到)?或其他什么?

      在一天结束时,我想要的状态是:

      1. 在IB中为父级和子级定义屏幕布局和位置
      2. 根据用户选择的按钮隐藏/显示儿童
      3. 每次显示子项时都会触发viewWillAppear,允许我更新内容
      4. 对于达到这种状态的任何建议表示赞赏,谢谢!

2 个答案:

答案 0 :(得分:7)

答案1:当您通过故事板添加子视图控制器(在本例中称为容器视图)时,将通过segue添加子项。不,它不是正常意义上的推送或呈现视图控制器的segue,而是在你的超级'中调用的方法。视图控制器是prepareForSegue。在界面构建器中,您可以将两个控制器之间的连接命名为普通segue,并在此实例中获取对视图控制器的引用。这需要addChildViewController,didMoveToParent等整个舞蹈的位置。

答案二:我认为解决你想要的状态是有意义的。我看起来你已经解决了#1和#2。至于让viewWillAppear再次开火,你必须让你的父母再次通过推送和弹出一个新的VC或者展示和解雇一个VC来重新开火。只是因为你将它设置为隐藏然后取消隐藏它不会再次触发它(隐藏基本上告诉绘图系统不渲染它)。

推荐的方法(来自Apple,原谅我,我不知道链接)是通过updateViewContraints或layoutSubviews在您的视图子类中完成所有更新。在视图控制器世界中,类似的方法是ViewDidLayoutSubviews。您可以通过调用[yourViewController.view setsNeedsLayout]向您的视图发出需要再次布局的信号。如需参考,请查看关于needsLayout的UIView上的文档。

当您按下按钮取消隐藏viewController时,您可能会想要做的事情如下:

1:在viewController上设置更新其内容的任何属性或调用方法

2:在viewControllers视图上调用setsNeedsLayout

3:取消隐藏它。

答案 1 :(得分:2)

每次展示孩子时,都不会为孩子们开火。调整你的想法。

在IB中创建容器视图和子视图时,它会设置一个嵌入segue以链接到子视图控制器。

我建议您为每个子视图控制器添加唯一的segue标识符,然后在prepareForSegue中,使用if / else if / else if语句匹配每个segue ID。找到segue Id时,将该子视图控制器保存在父级的属性中:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
  if ([segue.identifier isEqualToString: @"firstChildID")
    self.firstChildVC =   (FirstChildVC *) segue.destinationViewController;
  else if ([segue.identifier isEqualToString: @"secondChildID")
    self.secondChildVC =   (SecondChildVC *) segue.destinationViewController;
  else if ([segue.identifier isEqualToString: @"thirdChildID")
    self.thirdChildVC =   (ThirdChildVC *) segue.destinationViewController;
}

然后定义一个协议,用于与子视图控制器通信,告诉他们正在显示它们:

@protocol ChildVCProtocol

- (void) getReadyToShowView;
//whatever other methods
@end

然后让您的每个孩子VC符合该协议。将代码准备好在getReadyToShowView方法中显示。每次让孩子看到VC时都要调用该方法。