如何使用 StoryBoard 在 NavigationController 和 ViewController 之间传递值?

Posted

技术标签:

【中文标题】如何使用 StoryBoard 在 NavigationController 和 ViewController 之间传递值?【英文标题】:How can I pass value between NavigationController and ViewController with StoryBoard? 【发布时间】:2013-01-13 19:34:38 【问题描述】:

我有问题, 以下是我的故事板, 第一个控制器是TabBarController, 它与 A (ViewController) 的关系。

A 是ViewController, B 是 NavigationController,A 将页面更改为 B 由 modal segue C 是 ViewController,C 将通过 push 更改为另一个页面,所以我需要 NavigationController 好的,我想将值从 A 传递到 C, 现在我可以通过 prepareForSegue 将值从 A 传递到 B, 但是,由于B和C有关系但没有segue, 所以我不能通过 prepareForSegue 将值从 B 传递给 C!!!

【问题讨论】:

【参考方案1】:

故事板图像在这里有点误导。

当您选择 B 时,实际上您正在选择 B/C 组合,因为 NavController 的堆栈中始终至少有一个 viewController(这是他们的 topViewController 和他们的 [viewControllers objectAtIndex:0]) .

所以你确实有直接从 A 到 C 的关系。

您如何访问该控制器取决于您的 segue 是 modal 还是 push。在您的情况下,它是模态的,但我将描述两者,以便您看到区别。

无论哪种情况,要将数据传递给 C,您都需要在其头文件中声明一个属性

    @interface CviewController: UIViewContrller
    @property (assign) int dataFromA;
    @end

推动转场

在 push segue 中,实际上是 C 是destinationViewController,而不是 B。实际上 push segue 由 B 管理,B 是 A 和 C 的 UINavigationController。push segue 背后的代码形式如下[self.navigationController pushViewController:otherViewController];

在 AviewController 的 prepareForSegue 中:

    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
        
         CviewController* controller = segue.destinationViewController;
        [controller setDataFromA:self.data];
    

在情节提要中可能在两个 共享一个公共 UINavigationController 的 viewController 之间建立一条推线。但是,当你运行它时,你会得到一个崩溃错误:

'找不到用于 segue 'pushC' 的导航控制器。只有当源控制器由 UINavigationController 的实例管理时,才能使用推送 segue。'

每一个好的推送转场背后都有一个导航控制器。

模态转场

隐藏在模态 Segue 后面的代码是 UIViewController 方法- (void)presentViewController:(UIViewController *)viewControllerToPresent

在 NavController/ViewController 组合的模态 segue 中,目标 viewController 是 segue 线指向的任何内容。如果它指向一个 viewController,那就是 segue.destinationController (并且 UINavigationController 将被忽略,这不是你想要的);如果它指向 UINavigationController,在这种情况下,that 将是它的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*) 以避免编译器警告。

【讨论】:

您好,谢谢您的回答,我已经尝试过您的解决方案,但现在控制台显示以下错误“[UINavigationController setDataFromA:]: unrecognized selector sent to instance 0x7430850”。 @@怎么了? 你没有把消息发给 UINavigationController,你把它发给你 UIViewController (C) 您的故事板 Segue 正在从 A 运行到 B。删除它,并将其替换为从 A 到 C 运行的 segue。 如果我从 A 到 C 添加一个 segue,B 在哪里?我需要一个 NavigationController 因为 C 会推送到另一个 ViewController C 包含在 B 中。在情节提要中,您可以通过选择 C、菜单 > 编辑器 > 嵌入 > 导航控制器来“调用”B

以上是关于如何使用 StoryBoard 在 NavigationController 和 ViewController 之间传递值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS 中调用不同的 Storyboard?

如何使用 uiviewcontroller/storyboard 上的 uibutton 在 uipageviewcontroller 中推进页面

如何使用非基础本地化在 Xcode 中预览 Storyboard

如何使用 StoryBoard 在 UITableViewCell 内快速构建一个 collectionView

如何在没有 StoryBoard 的两个 ViewController 之间使用委托?

如何在现有的基于 Storyboard 的项目中设置 @EnvironmentObject?