The Storyboard image is a little misleading here.
When you segue to B, actually you are segueing to the B/C combo as NavControllers always have at least one viewController in their stack (which is their topViewController
and their [viewControllers objectAtIndex:0]
).
So you do have a relationship directly from A to C.
How you access that controller depends on whether your segue is modal or push. In your case it is modal, but I will describe both so you can see the difference.
In either case, to pass data to C, you need to declare a property in it's header file
@interface CviewController: UIViewContrller
@property (assign) int dataFromA;
@end
push segue
In a push segue, it is actually C that is the destinationViewController, not B. In fact the push segue is governed by B, which is the UINavigationController for both A and C. The code behind the push segue is of the form
[self.navigationController pushViewController:otherViewController];
In AviewController's prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller = segue.destinationViewController;
[controller setDataFromA:self.data];
}
It is possible in the storyboard to make a push segue line between two viewControllers that do not share a common UINavigationController. However when you run this you will get a crash error:
'Could not find a navigation controller for segue 'pushC'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'
Behind every good push segue lies a Navigation Controller.
modal segue
The code hiding behind a modal Segue is the UIViewController method
- (void)presentViewController:(UIViewController *)viewControllerToPresent
In a modal segue to a NavController/ViewController combo, the destination viewController is whatever the segue line points to. If it points to a viewController, that is the segue.destinationController (and the UINavigationController will be ignored, which is not what you want here); if it points to a UINavigationController, as in this case, that will be it's destinationController. But it is still straightforward to access the viewController, as it will be the navigation Controller's topViewController.
In AviewController's prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller =
(CviewController*)[[segue destinationViewController] topViewController];
[controller setDataFromA:self.data];
}
Note that in this case we have to use old-style [[message passing] syntax]. If we use modern.property.syntax we get a compile error. That's because the program does not know the type of desinationViewController, and refuses to accept topViewController as a property of an unknown type. But it is happy to [send [real messages]] to an unknown type. We also have to (typecast*) to avoid compiler warnings.