Storyboard – 参考AppDelegate中的ViewController

考虑以下情况:我有一个基于故事板的应用程序。 我将一个ViewController对象添加到故事板,将该ViewController的类文件添加到项目中,并在IB身份检查器中指定新类的名称。 现在我该如何从AppDelegate以编程方式引用此ViewController? 我已经做了一个与相关的类的variables,并将其转换为一个IBOutlet属性,但我没有看到任何能够在代码中引用新的ViewController的任何方式 – 任何尝试按Ctrl拖动连接不起作用。

即在AppDelegate中,我可以像这样到达基础ViewController

(MyViewController*) self.window.rootViewController 

但是故事板中包含的任何其他ViewController如何?

看看文档 -[UIStoryboard instantiateViewControllerWithIdentifier:] 。 这使您可以使用您在IB属性检查器中设置的标识从示意板中实例化视图控制器:

在这里输入图像描述

编辑添加示例代码:

 UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle: nil]; MyViewController *controller = (MyViewController*)[mainStoryboard instantiateViewControllerWithIdentifier: @"<Controller ID>"]; 

如果您使用XCode 5,则应以不同的方式进行操作。

  • UIStoryboardselect你的UIViewController
  • 转到右上方窗格上的Identity Inspector
  • 选中Use Storyboard IDcheckbox
  • 写一个唯一的ID到Storyboard ID字段

然后写你的代码。

 // Override point for customization after application launch. if (<your implementation>) { UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil]; YourViewController *yourController = (YourViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@"YourViewControllerID"]; self.window.rootViewController = yourController; } return YES; 

一般来说,系统应该用故事板处理视图控制器实例化。 你想要的是通过抓取对self.window.rootViewController的引用来遍历viewController层次结构,而不是初始化视图控制器,如果你已经正确地设置了storyboard,它应该已经被正确地初始化了。

所以,假设你的rootViewController是一个UINavigationController,然后你想发送一些东西给它的顶部视图控制器,你可以在你的AppDelegate的didFinishLaunchingWithOptions这样做:

 UINavigationController *nav = (UINavigationController *) self.window.rootViewController; MyViewController *myVC = (MyViewController *)nav.topViewController; myVC.data = self.data; 

在Swift中如果会非常相似:

 let nav = self.window.rootViewController as! UINavigationController; let myVC = nav.topViewController as! MyViewController myVc.data = self.data 

你真的不应该使用应用程序委托中的故事板ID来初始化视图控制器,除非你想绕过正常的方式加载故事板并自己加载整个故事板。 如果你不得不从AppDelegate初始化场景,你很可能做错了什么。 我的意思是想象一下,出于某种原因,想要将数据发送到视图控制器的方式下,AppDelegate不应该达到视图控制器堆栈设置数据的方式。 这不是它的业务。 它的业务是rootViewController。 让rootViewController处理自己的孩子! 所以,如果我通过删除info.plist文件中对它的引用来绕过正常的storyboard加载过程,我最多会使用instantiateViewControllerWithIdentifier:instantiateViewControllerWithIdentifier:化rootViewController:,如果它是一个容器,可能它的根,如UINavigationController 。 你想要避免的是实例化视图控制器已经由storyboard实例化。 这是我看到很多的问题。 总之,我不同意接受的答案。 这是不正确的,除非海报意味着从info.plist中删除故事板的加载,因为否则将加载2个故事板,这是没有意义的。 这可能不是内存泄漏,因为系统初始化根场景并将其分配给窗口,但是随后您又来到实例化并再次分配它。 你的应用程序是一个非常糟糕的开始!