跨子导航控制器传递数据
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的目标视图控制器是否是导航控制器并不重要
【讨论】:
以上是关于跨子导航控制器传递数据的主要内容,如果未能解决你的问题,请参考以下文章
如果我使用 prepareForSegue 传递数据,则无法嵌入导航控制器