使用 App Delegate 访问通过 Storyboard 创建的视图控制器

Posted

技术标签:

【中文标题】使用 App Delegate 访问通过 Storyboard 创建的视图控制器【英文标题】:Accessing a view controller created through Storyboard using the App Delegate 【发布时间】:2012-02-05 17:38:57 【问题描述】:

我正在使用情节提要开发 ios5 应用程序,并且我在视图控制器类中有一个方法,我想从 App Delegate 访问该方法。问题是,这个视图控制器是通过情节提要中的标签栏控制器实例化的,所以 App Delegate 无法直接调用我想要的方法......

要让视图控制器与 App Delegate 取得联系,只需使用:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];

是否有类似的简单方法可以指向已经实例化的视图控制器或类?

【问题讨论】:

【参考方案1】:

感谢 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;

【讨论】:

【参考方案2】:

您必须从应用委托遍历视图层次结构。假设AppDelegate 包含对UITabBarController 的引用,您可以使用viewControllers 属性或selectedViewController 属性来访问您的视图控制器。

【讨论】:

那么...从情节提要中的标签栏到应用程序委托的出口,然后找出标签栏的属性以找到我需要的视图控制器?有什么理由不直接从视图控制器本身创建一个出口,因为它也在情节提要中? 好的,没有办法从情节提要中创建到应用程序委托的出口,所以我的陈述有点不正确。应用程序委托上有一个由情节提要自动设置的窗口属性,它有一个 rootViewController 属性。这将是故事板中的第一个视图控制器。从那里您应该能够到达您需要的视图。 嘭!做到了……尽管遍历所有视图有点痛苦。谢谢,杰瑞! @jerry 可以为我的类似问题提出一些解决方案。 ***.com/questions/21373470/…【参考方案3】:

我可能会反过来做。在 AppDelegate 中创建一个方法调用 registerViewController 什么的。在每个 ViewController 中,使用自己的名称调用方法。然后在 AppDelegate 中,你可以做任何你想做的事。做各种练习都很麻烦

在 AppDelegate 中

- (void)registerViewController:(NSString *)name controller:(UIViewController *)controller

    if(_viewControllers == nil)
    
        _viewControllers = [[NSMutableDictionary alloc] init];

    

    [_viewControllers setObject:controller forKey:name];

在任何视图控制器中

- (void)viewDidLoad

    [super viewDidLoad];

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

在 AppDelegate 中

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

希望有帮助

BS

【讨论】:

好主意,但是 XViewController 应该在 dealloc 时从 _viewControllers 中删除,如果我需要在应用程序委托中访问许多视图控制器,我必须记住许多键。【参考方案4】:

如果您正在使用情节提要,并且想要情节提要中的 viewController 实例,则可以使用以下内容

UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
id viewcontroller = [mystoryboard instantiateViewControllerWithIdentifier:@"identifier"];

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

【讨论】:

这很好用。您对如何加载我的标签栏和导航控制器有任何指导吗?【参考方案5】:

我有一个更好的解决方案。您可以使用window.rootViewController.storyboard 获取对该视图的情节提要的引用。

【讨论】:

【参考方案6】:

在 AppDelegate 中,您可以简单地使用索引通过 UITabBarController 访问控制器:

UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
firstViewController = [[tabBarController viewControllers] objectAtIndex:0];
secondViewController = [[tabBarController viewControllers] objectAtIndex:1];
thirdViewController = [[tabBarController viewControllers] objectAtIndex:2];

如果您更改标签栏的顺序,这自然会搞砸。此外,如果您正在寻找层次结构更深的控制器,则需要做更多的工作。

【讨论】:

【参考方案7】:

斯威夫特

这是@infiniteLoop 答案的Swift 版本。

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

您需要将情节提要名称、视图控制器名称和视图控制器标识符替换为您在项目中使用的任何内容。

相关任务

Pass data to the view controller Present and dismiss a view controller modally

【讨论】:

以上是关于使用 App Delegate 访问通过 Storyboard 创建的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

如何从 UI 测试访问 App Delegate?

如何从app delegate访问NSViewController?

苹果mac怎么下载app stor以外的东西

设置 App Delegate 以管理数据

导航栏和导航工具栏不是来自 App Delegate

Cocoa:根据来自 App Delegate 的输入加载不同的视图控制器