ios Storyboard - 参考 AppDelegate 中的 ViewController
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8186375/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Storyboard - refer to ViewController in AppDelegate
提问by Matthias D
consider the following scenario: I have a storyboard-based app. I add a ViewController object to the storyboard, add the class files for this ViewController into the project and specify the name of the new class in the IB identity inspector. Now how am I going to refer to this ViewController programmatically from the AppDelegate? I've made a variable with the relevant class and turned it into an IBOutlet property, but I don't see any way of being able to refer to the new ViewController in code - any attempt to ctrl-drag a connection doesn't work.
考虑以下场景:我有一个基于故事板的应用程序。我将一个 ViewController 对象添加到故事板,将这个 ViewController 的类文件添加到项目中,并在 IB 身份检查器中指定新类的名称。现在我将如何从 AppDelegate 以编程方式引用这个 ViewController?我已经使用相关类创建了一个变量并将其转换为 IBOutlet 属性,但我没有看到任何能够在代码中引用新 ViewController 的方法 - 任何按住 ctrl 并拖动连接的尝试都不起作用.
i.e. within the AppDelegate I can get to the base ViewController like this
即在 AppDelegate 中,我可以像这样访问基本的 ViewController
(MyViewController*) self.window.rootViewController
but how about any other ViewController contained within the storyboard?
但是故事板中包含的任何其他 ViewController 怎么样?
回答by Robin Summerhill
Have a look at the documentationfor -[UIStoryboard instantiateViewControllerWithIdentifier:]
. This allows you to instantiate a view controller from your storyboard using the identifier that you set in the IB Attributes Inspector:
看一看的文档进行-[UIStoryboard instantiateViewControllerWithIdentifier:]
。这允许您使用您在 IB 属性检查器中设置的标识符从故事板实例化视图控制器:
EDITED to add example code:
编辑添加示例代码:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
bundle: nil];
MyViewController *controller = (MyViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: @"<Controller ID>"];
回答by Faruk Toptas
If you use XCode
5 you should do it in a different way.
如果您使用XCode
5,则应该以不同的方式进行。
- Select your
UIViewController
inUIStoryboard
- Go to the
Identity Inspector
on the right top pane - Check the
Use Storyboard ID
checkbox - Write a unique id to the
Storyboard ID
field
- 选择你
UIViewController
的UIStoryboard
- 转到
Identity Inspector
右上角的窗格 - 选中
Use Storyboard ID
复选框 - 向
Storyboard ID
字段写入唯一 ID
Then write your code.
然后写你的代码。
// 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;
回答by smileBot
Generally, the system should be handling view controller instantiation with a storyboard. What you want is to traverse the viewController hierarchy by grabbing a reference to the self.window.rootViewController
as opposed to initializing view controllers, which should already be initialized correctly if you've setup your storyboard properly.
通常,系统应该使用故事板处理视图控制器实例化。您想要的是通过获取对 的引用self.window.rootViewController
而不是初始化视图控制器来遍历 viewController 层次结构,如果您已正确设置故事板,则应该已经正确初始化。
So, let's say your rootViewController
is a UINavigationController and then you want to send something to its top view controller, you would do it like this in your AppDelegate's didFinishLaunchingWithOptions
:
所以,假设你rootViewController
是一个 UINavigationController,然后你想向它的顶视图控制器发送一些东西,你可以在你的 AppDelegate 中这样做didFinishLaunchingWithOptions
:
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;
In Swift if would be very similar:
在 Swift 中 if 会非常相似:
let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data
You really shouldn't be initializing view controllers using storyboard id's from the app delegate unless you want to bypass the normal way storyboard is loaded and load the whole storyboard yourself. If you're having to initialize scenes from the AppDelegate you're most likely doing something wrong. I mean imagine you, for some reason, want to send data to a view controller way down the stack, the AppDelegate shouldn't be reaching way into the view controller stack to set data. That's not its business. It's business is the rootViewController. Let the rootViewController handle its own children! So, if I were bypassing the normal storyboard loading process by the system by removing references to it in the info.plist file, I would at most instantiate the rootViewController using instantiateViewControllerWithIdentifier:
, and possibly its root if it is a container, like a UINavigationController. What you want to avoid is instantiating view controllers that have already been instantiated by the storyboard. This is a problem I see a lot. In short, I disagree with the accepted answer. It is incorrect unless the posters means to remove loading of the storyboard from the info.plist since you will have loaded 2 storyboards otherwise, which makes no sense. It's probably not a memory leak because the system initialized the root scene and assigned it to the window, but then you came along and instantiated it again and assigned it again. Your app is off to a pretty bad start!
您真的不应该使用来自应用程序委托的故事板 ID 来初始化视图控制器,除非您想绕过加载故事板的正常方式并自己加载整个故事板。如果您必须从 AppDelegate 初始化场景,那么您很可能做错了什么。我的意思是假设您出于某种原因想要将数据发送到堆栈下方的视图控制器,AppDelegate 不应该进入视图控制器堆栈以设置数据。那不是它的事。它的业务是 rootViewController。让 rootViewController 处理它自己的孩子!因此,如果我通过删除 info.plist 文件中对它的引用来绕过系统的正常故事板加载过程,我最多会使用实例化 rootViewControllerinstantiateViewControllerWithIdentifier:
,如果它是一个容器,则可能是它的根,如 UINavigationController。你想要避免的是实例化已经被故事板实例化的视图控制器。这是我经常看到的一个问题。简而言之,我不同意接受的答案。这是不正确的,除非海报意味着从 info.plist 中删除故事板的加载,否则你将加载 2 个故事板,这是没有意义的。这可能不是内存泄漏,因为系统初始化了根场景并将其分配给了窗口,但随后您又出现并再次实例化并再次分配了它。您的应用开局非常糟糕!
回答by Ofir Malachi
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];