通过应用程序委托访问使用故事板创建的视图控制器

14

我正在使用storyboard开发一个iOS5应用程序,我的一个视图控制器类中有一个方法,我希望能够从App Delegate中访问该方法。问题是,这个视图控制器是通过storyboard中的标签栏控制器实例化的,因此App Delegate无法直接调用我想要的方法...

要让一个视图控制器与App Delegate联系起来,只需使用:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
有没有类似的简单方法可以指向一个已经实例化的视图控制器或类?
7个回答

15

感谢Jerry(以上),以下是帮我得到所需结果的代码:

    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;
}

10
你需要从应用程序代理开始遍历视图层次结构。假设AppDelegate持有对UITabBarController的引用,你可以使用viewControllers属性或selectedViewController属性来获取到你的视图控制器。

那么...从Storyboard中的选项卡栏到应用程序委托的出口,然后找出选项卡栏的属性以找到我需要的视图控制器?有没有理由直接从视图控制器本身创建一个直接出口,因为它也在Storyboard中呢? - Amos
6
好的,从故事板中无法创建到应用委托的出口,因此我的陈述有点不正确。应用委托上有一个窗口属性,它会被故事板自动设置,并且它具有一个rootViewController属性。这将是故事板中的第一个视图控制器。从那里,您应该能够获取到您需要的视图。 - Jerry
搞定了!虽然遍历所有视图有点麻烦。谢谢,Jerry! - Amos
@Jerry,你能为我类似的问题提供一些解决方案吗?https://dev59.com/Qnvaa4cB1Zd3GeqPHcb9 - Suraj K Thomas

10

我可能会反过来做。在AppDelegate中创建一个名为registerViewController的方法或其他方法。在每个ViewController中,使用自身的名称调用该方法。然后在AppDelegate中,您可以随意进行任何操作。这样做所有类型的钻研都很混乱。

在AppDelegate中

- (void)registerViewController:(NSString *)name controller:(UIViewController *)controller
{
    if(_viewControllers == nil)
    {
        _viewControllers = [[NSMutableDictionary alloc] init];

    }

    [_viewControllers setObject:controller forKey:name];
}
在任何 ViewController 中。
- (void)viewDidLoad
{
    [super viewDidLoad];

    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    [appDelegate registerViewController:@"feelings" controller:self];
}

在AppDelegate中

XViewController *vc = (XViewController *)[_viewControllers objectForKey:@"X"];
[X startSpinner];

希望这能帮到你。

胡说八道。


好主意,但是在dealloc时应该从_viewControllers中移除XViewController,如果有许多视图控制器需要在应用程序委托中访问,我必须记住许多键。 - Nick

7
如果您正在使用Storyboard并且想要获取Storyboard中ViewController的实例,您可以按照以下方式操作:
UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
id viewcontroller = [mystoryboard instantiateViewControllerWithIdentifier:@"identifier"];

这里的“标识符”是在特定视图控制器的“故事板ID”中提供的名称,在“身份检查器”中的“身份”部分。


这个很好用。您有没有关于如何加载我的选项卡栏和导航控制器的指导? - mreynol

6

我有一个更好的解决方案。你可以使用window.rootViewController.storyboard来获取那个视图所属的storyboard的引用。


2
在AppDelegate中,您可以通过使用索引来访问UITabBarController中的控制器:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
firstViewController = [[tabBarController viewControllers] objectAtIndex:0];
secondViewController = [[tabBarController viewControllers] objectAtIndex:1];
thirdViewController = [[tabBarController viewControllers] objectAtIndex:2];

如果您更改选项卡栏的排序,这个自然会出现混乱。此外,如果您正在查找更深层次的控制器,则需要做更多的工作。


1

Swift

这是@infiniteLoop答案的Swift版本。

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myViewController = storyboard.instantiateViewControllerWithIdentifier("identifier") as! MyViewController

你需要用你的项目中使用的故事板名称、视图控制器名称和视图控制器标识符替换它们。 相关任务

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接