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,则应以不同的方式进行操作。
- 在
UIStoryboard
select你的UIViewController
- 转到右上方窗格上的
Identity Inspector
- 选中
Use Storyboard ID
checkbox - 写一个唯一的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个故事板,这是没有意义的。 这可能不是内存泄漏,因为系统初始化根场景并将其分配给窗口,但是随后您又来到实例化并再次分配它。 你的应用程序是一个非常糟糕的开始!