[英]View Controller Containment when using Interface Builder
我正在尝试使用Interface Builder定义一系列容器视图控制器(可能是我的第一个错误)。 在故事板中,我创建了顶视图控制器,添加了3个容器视图,自动将每个子视图控制器添加到故事板。 我为每个容器视图添加了一个插座,并且能够通过隐藏/显示容器视图成功地操纵子视图。 真的没有太多代码可言,它只是:
-(IBAction) button1Pushed:(id)sender
{
containerView2.hidden = true;
containerView1.hidden = false;
}
虽然这有效,但我需要更新每个节目的内容。 viewWillAppear(和相关函数)仅在初始创建时触发子视图控制器,而不是在隐藏/显示容器时触发。 我想我可以添加类似的东西:
[childVC1 updateContent];
containerView1.hidden = false;
但我希望我可以依赖viewWillAppear(以及相关的功能)。 我尝试了一些成功有限的事情,并提出了几个问题:
[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处理的示例代码有多少,我需要实现多少?
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:当您通过故事板添加子视图控制器(在本例中称为容器视图)时,子项将通过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:取消隐藏它。
每次显示子视图时,viewWillAppear都不会触发。 调整你的想法。
在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可见时调用该方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.