跨子导航控制器传递数据

Posted

技术标签:

【中文标题】跨子导航控制器传递数据【英文标题】:Pass data across child navigation controllers 【发布时间】:2012-03-23 00:24:42 【问题描述】:

概述

我有一个 ios 项目,其中包含 2 个导航控制器,如下图所示。

当它从 AAA 转移到 CCC 时,我想传递一些数据,但 AAA 和 CCC 之间有一个导航控制器。

根据 Apple 的文档,UINavigationController 不应该被子类化,所以我不能创建委托和传递数据。

问题:

如何将数据从 AAA 传递到 CCC? 有什么变通方法来实现这一点吗?

【问题讨论】:

为什么在 AAA 和 CCC 之间有额外的导航控制器?为什么不直接从 AAA 转到 CCC? 【参考方案1】:

如果你有一个指向导航控制器的指针,你可以得到它的 viewControllers 数组。在该数组中,objectAtIndex:0 将是 CCC。

【讨论】:

当您从 AAA 切换到导航控制器时,还没有创建 CCC。如果我错了,请告诉我 我在另一篇文章中找到了一个不错的解决方案(链接如下):***.com/questions/8450545/… appDelegate 可以包含可以从任何地方访问的代表。 不要使用应用委托作为传递全局状态的来源。 CCC 将在创建导航控制器的同时创建。 这是一篇关于cocoawithlove.com/2008/11/…主题的好博文【参考方案2】:

对于不清楚如何实施已接受答案的任何人,这里有一个代码示例,可以更清楚地解释如何“have a pointer to the navigation controller”。下面的代码将一个 NSString 从 AAA (AAAViewController) 传递到 CCC (CCCViewController),并带有一个名为“ToCCC”的标识符用于 segue。

1) 在CCCViewController.h 中创建指向foo 的指针。

//  CCCViewController.h

#import <UIKit/UIKit.h>

@interface CCCViewController : UITableViewController

@property (strong, nonatomic) NSString *foo;

@end

2) 在AAAViewController.m 中,创建一个指向CCCViewController 的指针(通过导航控制器),然后设置foo

//  AAAViewController.m

#import "AAAViewController.h"
#import "CCCViewController.h" // Note the import statement for CCC.

@implementation AAAViewController

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    if ([segue.identifier isEqualToString: @"ToCCC"])
    
        CCCViewController *ccc = [[segue.destinationViewController viewControllers] objectAtIndex: 0];
        ccc.foo = @"A string passed from AAA";
    


@end

3) 在CCCViewController.m 中使用foo 执行某些操作(例如,将其记录到控制台)。

//  CCCViewController.m

#import "CCCViewController.h"

@implementation CCCViewController

- (void)viewDidLoad

    [super viewDidLoad];

    // Log foo to the console.
    NSLog(@"%@", _foo);


@end

【讨论】:

【参考方案3】:

一个不错的解决方案是在 UIStoryboardSeque 上创建一个类别

UIStoryboardSegue+TopLevel.h

@interface UIStoryboardSegue (TopLevel)

@property (readonly) id topLevelDestinationViewController;

@end

UIStoryboardSegue+TopLevel.m

@implementation UIStoryboardSegue (TopLevel)

- (id)topLevelDestinationViewController

    id dest = self.destinationViewController;
    if ([dest isKindOfClass:[UINavigationController class]]) 
        UINavigationController* nav = dest;
        dest = nav.topViewController;
    
    return dest;


@end

然后使用类别

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

    [super prepareForSegue:segue sender:sender];

     if ([[segue topLevelDestinationViewController] respondsToSelector:@selector(setSomeProperty:)]) 
     
        [[segue topLevelDestinationViewController] performSelector:@selector(setSomeProperty:) withObject:self.someProperty];
     

这样你的代码可以变得非常通用,并且segue的目标视图控制器是否是导航控制器并不重要

【讨论】:

以上是关于跨子导航控制器传递数据的主要内容,如果未能解决你的问题,请参考以下文章

将导航控制器添加到视图时无法传递数据

Swift:将数据从视图控制器传递到导航控制器

如果我使用 prepareForSegue 传递数据,则无法嵌入导航控制器

导航控制器未将数据从 tableview 传递到 viewcontroller

我可以用 xcode 中的“导航控制器后退按钮”传递数据吗

使用导航栏按钮项和核心数据在视图控制器之间传递日期