Ответ 1
Изображение раскадровки здесь немного вводит в заблуждение.
Когда вы переходите к B, на самом деле вы переходите на комбо B/C, так как NavControllers всегда имеют по крайней мере один viewController в своем стеке (это их topViewController
и их [viewControllers objectAtIndex:0]
).
Итак, у вас есть отношения непосредственно от A до C.
Как вы получаете доступ к этому контроллеру, зависит от того, является ли ваш segue модальным или нажмите. В вашем случае это модально, но я опишу оба, чтобы вы могли видеть разницу.
В любом случае, чтобы передать данные на C, вам нужно объявить свойство в его заголовочном файле
@interface CviewController: UIViewContrller
@property (assign) int dataFromA;
@end
push segue
В режиме push segue на самом деле это C, который является destinationViewController, а не B. Фактически, push-сегмент управляется с помощью B, который является UINavigationController для A и C. Код, лежащий в основе push-сегмента, имеет форму [self.navigationController pushViewController:otherViewController];
В AviewController prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller = segue.destinationViewController;
[controller setDataFromA:self.data];
}
В раскадровке можно сделать линию push segue между двумя viewControllers, которые не имеют общего UINavigationController. Однако при запуске вы получите сообщение об ошибке:
'Не удалось найти контроллер навигации для segue' pushC '. Push segues может использоваться только тогда, когда управляющий источник управляется экземпляром UINavigationController. '
За каждым хорошим нажатием кнопки находится навигационный контроллер.
modal segue
Кодом, скрывающимся за модальным Segue, является метод UIViewController - (void)presentViewController:(UIViewController *)viewControllerToPresent
В modal segue для комбинации NavController/ViewController целевой viewController - это то, на что указывает линия segue. Если он указывает на viewController, то это будет segue.destinationController(и UINavigationController будет проигнорирован, что вы не хотите здесь); если он указывает на UINavigationController, как в этом случае, это будет destinationController. Но доступ к viewController по-прежнему несложно, так как это будет диспетчер навигации topViewController.
В AviewController prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
CviewController* controller =
(CviewController*)[[segue destinationViewController] topViewController];
[controller setDataFromA:self.data];
}
Обратите внимание, что в этом случае мы должны использовать синтаксис [[передача сообщений] в старом стиле]. Если мы используем modern.property.syntax, мы получаем ошибку компиляции. Это потому, что программа не знает тип desinationViewController и отказывается принимать topViewController как свойство неизвестного типа. Но он рад [отправить [реальные сообщения]] на неизвестный тип. Нам также необходимо (typecast *) избежать предупреждений компилятора.