可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm working on an iOS5 app using storyboard, and I have a method in a view controller class that i'd like to access from the App Delegate. The trouble is, this view controller gets instantiated via a tab bar controller in storyboard, so the App Delegate has no direct way of calling the method I want...
For a view controller to get in touch with the App Delegate, all one has to do is use:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
Is there a similarly easy way of pointing to an already-instantiated view controller or class?
回答1:
You'll have to traverse the view hierarchy from the app delegate. Assuming the AppDelegate
holds a reference to the UITabBarController
, you could use the viewControllers
property or selectedViewController
property to get to your view controller.
回答2:
Thanks to Jerry (above), here's the code that got me what I wanted:
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
MasterViewController *result;
//check to see if navbar "get" worked
if (navigationController.viewControllers)
//look for the nav controller in tab bar views
for (UINavigationController *view in navigationController.viewControllers) {
//when found, do the same thing to find the MasterViewController under the nav controller
if ([view isKindOfClass:[UINavigationController class]])
for (UIViewController *view2 in view.viewControllers)
if ([view2 isKindOfClass:[MasterViewController class]])
result = (MasterViewController *) view2;
}
回答3:
I probably would do it in reverse. Create a method in AppDelegate call registerViewController or something. In every ViewController, call the method with itself with a name. Then in AppDelegate, you can do whatever you want afterward. It is messy to do all sort of drill
In AppDelegate
- (void)registerViewController:(NSString *)name controller:(UIViewController *)controller
{
if(_viewControllers == nil)
{
_viewControllers = [[NSMutableDictionary alloc] init];
}
[_viewControllers setObject:controller forKey:name];
}
In any ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate registerViewController:@"feelings" controller:self];
}
In AppDelegate
XViewController *vc = (XViewController *)[_viewControllers objectForKey:@"X"];
[X startSpinner];
Hope this help
BS
回答4:
If you are using a storyboard, and you want instance of a viewController in storyboard you can use the following
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
id viewcontroller = [mystoryboard instantiateViewControllerWithIdentifier:@"identifier"];
Here the 'identifier' is the name provided in the particular viewController's 'storyBoard ID' in 'Identity' section in 'Identity Inspector'.
回答5:
I have a better solution. You can use window.rootViewController.storyboard
to get a reference to the storyboard of that view.
回答6:
In the AppDelegate, you could simply use indexes to access the controllers via UITabBarController:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
firstViewController = [[tabBarController viewControllers] objectAtIndex:0];
secondViewController = [[tabBarController viewControllers] objectAtIndex:1];
thirdViewController = [[tabBarController viewControllers] objectAtIndex:2];
Naturally, this will get messed up if you change the ordering of the tab bar. Also, if you're looking for a controller deeper in the hierarchy, you need to do a bit more legwork.
回答7:
Swift
This is the Swift version of @infiniteLoop's answer.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myViewController = storyboard.instantiateViewControllerWithIdentifier("identifier") as! MyViewController
You need to replace the storyboard name, view controller name, and view controller identifier with whatever you used in your project.
Related tasks
- Pass data to the view controller
- Present and dismiss a view controller modally