21

I have a storyboard set up in XCode and have a MainViewController. In the MainViewController I have added a ContainerView which naturally creates a Segue with another VIewController.

In my MainViewController.m file I have set up data and want to link this data to a label in the ContainerView however I thought I could click on the File's Owner and do this but of course I can't because they are 2 different viewcontrollers now.

Can someone please help me because I'm struggling with this. There must be an easy way but I can't crack it!

Thank you

Segev
  • 19,035
  • 12
  • 80
  • 152
Omar
  • 979
  • 3
  • 16
  • 26

4 Answers4

28

You can use prepareForSegue just like any other two controllers -- that method will be called after the two controllers are instantiated, but before either viewDidLoad runs. The other way to do this is to use the parent controller's childViewControllers property (the embedded controller is a child). So, the child will be self.childViewControllers[0].

After Edit:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"EmbedSegue"]) {
        MyEmbeddedController *embed = segue.destinationViewController;
        embed.labelString = self.stringToPass;
    }
}

Of course, you have to change the names to what you have. Make sure the name you give to the segue in IB matches the one you check for in the if statement. In this example labelString is a string property you set up in your embedded controller. Then in that controller's viewDidLoad method, you can set the value of the label with that string.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • I don't quite understand. I'm fairly new to this so if you'd be so kind to provide some example of code then that would be really helpful. – Omar Jul 20 '13 at 15:09
  • Thanks for that. So now my code looks something like this: - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@"MainChild"]) { MainViewController *embed = segue.destinationViewController; embed.labelNextPrayer = self.labelNextPrayer; } } However that label I am calling I still can't link to anything in the ContainerView which is called 'View Controller' – Omar Jul 20 '13 at 15:26
  • @Omar, you can't do it that way -- the viewDidLoad methods of the two controllers hasn't run yet at the time prepareForSegue is called, so you can't access the labels of the child from the parent. In any case, you shouldn't do that anyway -- let the child populate its own labels. You should pass the data (strings or whatever) to properties in the child like I said in my edit. – rdelmar Jul 20 '13 at 15:28
  • @redelmar Ok so just to break it down. I have some 'prayer times' which run in the ViewDidLoad method and in there it reads if ([key isEqual: @"(null)"]) { [self getDataFromJson2]; } else { labelNextPrayer.text = key; } I want to call that labelNextPrayer.text and link it to a UILabel in ContainerView which is connected via the Segue. Im just stuck on that part – Omar Jul 20 '13 at 15:34
  • @Omar, and what do you want to do with that? Which controller is that in? Which controller has the label, labelNextPlayer? You need to explain more fully. – rdelmar Jul 20 '13 at 15:37
  • @redelmar That code is in MainViewController. I have synthesised the property so when I go to MainViewController in my storyboard I can link labelNextPrayer to any UILabel in MainViewController because it is an Outlet. That is perfectly normal. However, I have created a Container View which automatically creates a separate ViewController linked via Segue. The problem I have is that because the ContainerView is now a separate ViewController, I can't attach labelNextPrayer to a UILabel in Container View – Omar Jul 20 '13 at 15:40
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33830/discussion-between-omar-and-rdelmar) – Omar Jul 20 '13 at 15:44
7

This is pretty much the same answer as the one by rdelmar only in Swift.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let embeddedVC = segue.destinationViewController as? MyEmbeddedController where segue.identifier == "EmbedSegue" {
        embeddedVC.labelString = self.stringToPass
    }
}

"EmbedSegue" has to the segue identifier you set in Interface Builder.

Community
  • 1
  • 1
orkoden
  • 18,946
  • 4
  • 59
  • 50
0
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // Make sure your segue name in storyboard is the same as this line
    if ([[segue identifier] isEqualToString:@"YOUR_SEGUE_NAME_HERE"])
    {
        // Get reference to the destination view controller
        YourViewController *vc = [segue destinationViewController];

        // Pass any objects to the view controller here, like...
        [vc setMyObjectHere:object];
    }
}

I should also mention that because you are using a Container view, prepareForSegue will be triggered when you'll present the ViewController that holds the Container.

Segev
  • 19,035
  • 12
  • 80
  • 152
  • Thank you very much. I'm just a little confused about the '[vc setMyObjectHere:object];' section. I have a whole heap of code in the ViewDidLoad method with Outlets which are picked up by the MainViewController. I simply want to be able to link these Outlets to elements in the Container View (which is a separate view controller linked with a Segue) – Omar Jul 20 '13 at 15:20
  • You should pass the data in the code above. If its strings, create an array of string and pass that. Check out my answer here about passing data: http://stackoverflow.com/a/16670995/1578927 – Segev Jul 20 '13 at 15:35
0

Answer for Swift 4:

if let controller = segue.destinationController as? MyEmbeddedController, segue.identifier!.rawValue == "EmbedSegue" {
    controller.labelString = self.stringToPass
}
David Boyd
  • 6,501
  • 3
  • 21
  • 13