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

时间:2012-11-07 22:07:29

标签: ios objective-c swift uiviewcontroller containers

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

情景:

example

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

它们之间有一个区别,我可以使用吗?

11 个答案:

答案 0 :(得分:351)

是的,您可以使用segue访问子视图控制器(及其视图和子视图)。使用Storyboard中的Attributes检查器为segue提供标识符(例如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...
   }
}

答案 1 :(得分:54)

您只需使用self.childViewControllers.lastObject即可(假设您只有一个孩子,否则请使用objectAtIndex:)。

答案 2 :(得分:23)

用于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
    }
}

答案 3 :(得分:15)

prepareForSegue方法有效,但它依赖于segue标识符魔术字符串。也许有更好的方法。

如果你知道你所追求的VC的类,你可以用计算属性非常巧妙地做到这一点:

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

这取决于childViewControllers。虽然我同意依靠第一个可能很脆弱,但是你所寻找的课程命名使它看起来非常可靠。

答案 4 :(得分:9)

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

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

这只会迭代子列表,直到达到第一场比赛。

答案 5 :(得分:8)

当您需要来自父级的控制时,

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

答案 6 :(得分:1)

我使用Code代码:

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

答案 7 :(得分:1)

如果有人正在寻找 Swift 3.0

然后可以访问

viewController1 viewController2 等。

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")
}

答案 8 :(得分:1)

在视图控制器的类型上使用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
  }
}

答案 9 :(得分:1)

通用你可以做一些甜蜜的事情。这是Array的扩展名:

extension Array {
    func firstMatchingType<Type>() -> Type? {
        return first(where: { $0 is Type }) as? Type
    }
}

然后您可以在viewController中执行此操作:

var viewControllerInContainer: YourViewControllerClass? {
    return childViewControllers.firstMatchingType()!
}

答案 10 :(得分:0)

你可以这样写

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