无法从模态 ViewController 访问 UITabBarController

Posted

技术标签:

【中文标题】无法从模态 ViewController 访问 UITabBarController【英文标题】:Cannot access UITabBarController from modal ViewController 【发布时间】:2014-08-06 18:21:29 【问题描述】:

我有一个基于UITabBarController 的应用程序,其中我的登录页面 由默认选项卡的VC(UITabBarController 索引0)以模态方式呈现,并由dismissViewControllerAnimated: 以模态方式关闭。

从我的设置页面我有一个注销按钮,如果用户立即重新登录,我必须调用[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];,然后重置UITabBarController' s selectedIndex 属性,以便摆脱设置页面并返回到开始的 tabBar 选项卡。所以我这样做:

-(void)connectionDidFinishLoading:(NSURLConnection *)connection

    NSString* responseString = [[NSString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding];

    /*Succesful Login*/
    if([responseString isEqualToString:@"success"])
    
        UITabBarController *tabBarController = (UITabBarController *)self.presentingViewController;

        if (tabBarController)
            NSLog(@"I have a tab bar~");
            [self.tabBarController setSelectedIndex:0];
        
        else
            NSLog(@"I don't have a tab bar~");
        

        //dismisses from a second, immediate, re-login attempt
        [self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
        //dismisses from first login attempt
        [self dismissViewControllerAnimated:YES completion:nil];

        NSLog(@"Succesful login.");
    

在这种情况下,setSeletedIndex: 方法不起作用,因为该方法本质上是创建 tabBarController 的一个新实例,而实际显示的是原始实例。我似乎无法访问已经存在的 UITabBarController,它位于我的模态显示登录页面之前。

编辑:

我已经尝试使用这个条件来检查它的存在:

if (self.tabBarController)
    NSLog(@"I have a tab bar~");
    //[self.tabBarController setSelectedIndex:0];

else
    NSLog(@"I don't have a tab bar~");

我什至将 self.tabBarController 更改为 self.presentingViewController.tabBarController 并获得 nil 和 self.presentingViewController.presentingViewController.tabBarController 并获得 nil,我如何访问以前存在的 @987654329 @?

目标: 访问应用程序的 UITabBarController,它出现在登录页面之前。 (访问 Appdelegate 的 UITabBarController)

【问题讨论】:

您发布的代码中没有任何内容可以创建标签栏控制器的新实例。如果你记录 self.presentingViewController 和 self.tabBarController 它们会给你什么?另外,根据您的描述,听起来您已经在索引 0 的选项卡上(显示模态),那么您期望 setSelectedIndex:0 会做什么? 找到了答案,而 self.tabBarController 给了我零,这就是问题所在.. 您的问题不清楚。请注意,人们会花时间来帮助您。您至少可以澄清您的问题,以便更轻松地为您提供“解决方案”。祝你好运。 不,我感谢您的帮助,并为不清楚的地方感到抱歉,这是我第一次不得不处理这个问题,这真的很令人困惑。我不得不重新配置我的整个应用程序,感谢您抽出宝贵时间。 【参考方案1】:

您的用例非常适合委托。

在登录的头文件中,定义一个委托。例如,

@class Login
@protocol LoginDelegate <NSObject>
@required
- (void) userDoneWithLoginController:(Login *) controller;
@end

@interface Login: UIViewController

@property (weak, nonatomic) id<LoginDelegate> viewDelegate;

@end

然后,在控制传递到登录页面之前,您的呈现视图控制器 segue 可以通过在呈现视图控制器的 prepareForSegue 中设置此“viewDelegate”对象,将自己设置为登录视图控制器的委托。 [如果您想澄清这一点,请告诉我。]

此外,呈现视图控制器将实现所需的方法——调用时可以简单地关闭登录页面

-(void)  userDoneWithLoginController:(Login *) controller

    [controller dismissViewControllerAnimated:YES completion:nil];

完成此操作后,登录页面只需在完成时调用其委托方法,因此:

[self.viewDelegate userDoneWithLoginController:self];

维奥拉!

这是在 ios 中关闭模式视图的首选方式。调用控制器应该是关闭视图的控制器。尽量避免让视图控制器自行关闭。相反,让他们的呼叫/呈现控制器(代表)解雇他们。

【讨论】:

这很好,但这不是解决此问题的方法,请尝试再次阅读编辑。我现在不关心首选的解雇技术。我正处于原型设计阶段。我只需要访问在presentingViewController 之前直接可见的UITabBarController 将它传递给正在呈现的视图控制器有什么问题?如果你想做你描述的事情,你可以将 tabBarController 作为变量传递。 这需要更多的努力,因为您使用的是 segues 和 prepareForSegue:。我宁愿保持严格的程序化,只需从我的 appDelegate 访问 tabBarController。 我对你最后的评论感到困惑。您真的是说设置变量需要更多努力吗? 不抱歉,我的意思是重新配置我的设置以遵循您的方法需要更多的努力。我目前没有使用 segues 进行登录,这一切都是以模态和编程方式完成的。以您的方式设置变量很好,但需要 segue 和 prepareForSegue:【参考方案2】:

以下应该有效。

// check that the vc presenting your current modal vc is a tab bar controller
if ([self.presentingViewController isKindOfClass:[UITabBarController class]]) 

    // get the pointer of type UITabBarController
    UITabBarController *tabBarController = (UITabBarController *)self.presentingViewController;

    // set to the desired tab
    tabBarController.selectedIndex = 2;


// dismiss the current modal vc
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

【讨论】:

【参考方案3】:

我相信我找到了解决方案。

我可以像这样从 Appdelegate 访问应用程序的 UITabBarController

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[[appDelegate myTabBar] setSelectedIndex:0];

【讨论】:

这可能有效,但我不会称其为解决方案,它更像是一种变通方法。你不应该这样做。您是否尝试过我在评论中建议的日志记录? 啊,我看到了我遗漏的问题... 设置页面 是从 tabBar 的第三个索引(索引 3)的导航栏访问的。因此,当 self.presentingViewController.presentingViewController(第 3 个选项卡)关闭登录(连同设置)时,它会将 tabBar 留在索引 3.. 这需要为 0。

以上是关于无法从模态 ViewController 访问 UITabBarController的主要内容,如果未能解决你的问题,请参考以下文章

使用“模态推送”到 viewController 并且无法在顶部添加 UINavigationItem-(Controller, Bar)

如何将数据从模态 ViewController 传输到父 ViewController?

如何从 UIAlertcontroller 关闭模态 ViewController

从模态 ViewController 呈现 UIImagePickerController

从 SubView 呈现模态 ViewController

UIViewController 从 viewController 和后退按钮模态加载 UINavigationController [重复]