从父iOS访问容器视图控制器

在iOS6中,我注意到了新的容器视图,但我不太清楚如何从包含视图访问它的控制器。

场景:

例

我想从容纳视图的视图控制器访问警报视图控制器中的标签。

他们之间有一段时间,我可以用吗?

是的,你可以使用segue来访问子视图控制器(及其视图和子视图)。 使用Storyboard中的属性检查器给alertview_embed一个标识符(如alertview_embed )。 然后让父视图控制器(容器视图)执行这样一个方法:

 - (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { NSString * segueName = segue.identifier; if ([segueName isEqualToString: @"alertview_embed"]) { AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController]; AlertView * alertView = childViewController.view; // do something with the AlertView's subviews here... } } 

你可以简单地使用self.childViewControllers.lastObject (假设你只有一个孩子,否则使用objectAtIndex: self.childViewControllers.lastObject

Swift编程

你可以这样写

 var containerViewController: ExampleViewController? override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // you can set this name in 'segue.embed' in storyboard if segue.identifier == "checkinPopupIdentifierInStoryBoard" { let connectContainerViewController = segue.destinationViewController as ExampleViewController containerViewController = connectContainerViewController } } 

prepareForSegue方法的作品,但它依赖于segue标识魔术string。 也许有更好的办法。

如果你知道你所使用的VC的类,你可以用一个计算的属性非常整齐的做到这一点:

 var camperVan: CamperVanViewController? { return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first // This works because `flatMap` removes nils } 

这依赖于childViewControllers 。 虽然我认为依靠第一个方法可能会很脆弱,但是要命名你所寻求的这个类使得这看起来相当稳固。

当你需要父母的控制时, self.childViewControllers更加相关。 例如,如果子控制器是一个表视图,并且想要强制重新加载它,或者通过父视图控制器上的button点击或任何其他事件来更改属性,则可以通过访问ChildViewController的实例而不是通过prepareForSegue来完成。 两者都有不同的应用方式。

Swift 3更新的答案,使用一个计算属性:

 var jobSummaryViewController: JobSummaryViewController { get { let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController }) return ctrl as! JobSummaryViewController } } 

这只会迭代孩子的列表,直到达到第一个匹配。

我使用代码如:

 - (IBAction)showCartItems:(id)sender{ ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:@"ListOfCartItemsViewController"]; [self addChildViewController:listOfItemsVC]; } 

如果有人正在寻找Swift 3.0

然后可以访问viewController1viewController2等等。

 let viewController1 : OneViewController! let viewController2 : TwoViewController! // Safety handling of optional String if let identifier: String = segue.identifier { switch identifier { case "segueName1": viewController1 = segue.destination as! OneViewController break case "segueName2": viewController2 = segue.destination as! TwoViewController break // ... More cases can be inserted here ... default: // A new segue is added in the storyboard but not yet including in this switch print("A case missing for segue identifier: \(identifier)") break } } else { // Either the segue or the identifier is inaccessible print("WARNING: identifier in segue is not accessible") } 

在视图控制器的types上使用Swift的switch语句还有另一种方法:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.destination { case let aViewController as AViewController: self.aViewController = aViewController case let bViewController as BViewController: self.bViewController = bViewController default: return } } 

你可以这样写

 - (IBAction)showDetail:(UIButton *)sender { DetailViewController *detailVc = [self.childViewControllers firstObject]; detailVc.lable.text = sender.titleLabel.text; } }