Access Container View Controller from Parent iOS

IosObjective CSwiftUiviewcontrollerUicontainerview

Ios Problem Overview


in iOS6 I noticed the new Container View but am not quite sure how to access it's controller from the containing view.

Scenario:

example

I want to access the labels in Alert view controller from the view controller that houses the container view.

There's a segue between them, can I use that?

Ios Solutions


Solution 1 - Ios

Yes, you can use the segue to get access the child view controller (and its view and subviews). Give the segue an identifier (such as alertview_embed), using the Attributes inspector in Storyboard. Then have the parent view controller (the one housing the container view) implement a method like this:

- (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...
   }
}

Solution 2 - Ios

You can do that simply with self.childViewControllers.lastObject (assuming you only have one child, otherwise use objectAtIndex:).

Solution 3 - Ios

for Swift Programming

you can write like this

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

Solution 4 - Ios

The prepareForSegue approach works, but it relies on the segue identifier magic string. Maybe there's a better way.

If you know the class of the VC you're after, you can do this very neatly with a computed property:

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

This relies on childViewControllers. While I agree it could be fragile to rely on the first one, naming the class you seek makes this seem quite solid.

Solution 5 - Ios

An updated answer for Swift 3, using a computed property:

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

This only iterates the list of children until it reaches the first match.

Solution 6 - Ios

self.childViewControllers is more relevant when you need control from the parent. For instance, if the child controller is a table view and you want to reload it forcefully or change a property via a button tap or any other event on Parent View Controller, you can do it by accessing ChildViewController's instance and not via prepareForSegue. Both have their applications in different ways.

Solution 7 - Ios

There is another way using Swift's switch statement on the type of the view controller :

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

Solution 8 - Ios

I use Code like:

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

Solution 9 - Ios

In case someone is looking for Swift 3.0,

viewController1, viewController2 and so on will then be accessible.

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

Solution 10 - Ios

With generic you can do some sweet things. Here is an extension to Array:

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

You can then do this in your viewController:

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

Solution 11 - Ios

you can write like this

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAdam WaiteView Question on Stackoverflow
Solution 1 - IosPeter EView Answer on Stackoverflow
Solution 2 - IosrdelmarView Answer on Stackoverflow
Solution 3 - IosSruit A.SukView Answer on Stackoverflow
Solution 4 - IosSimplGyView Answer on Stackoverflow
Solution 5 - IosRobin DaughertyView Answer on Stackoverflow
Solution 6 - IosGautam JainView Answer on Stackoverflow
Solution 7 - IosJoanna CarterView Answer on Stackoverflow
Solution 8 - IosMannam BrahmamView Answer on Stackoverflow
Solution 9 - IosMarco LeongView Answer on Stackoverflow
Solution 10 - IosSunkasView Answer on Stackoverflow
Solution 11 - IosKhurshidView Answer on Stackoverflow