在 TabBarController 上切换选项卡时关闭所有详细视图

Dismiss all Detail Views when switching Tabs on TabBarController

我的 iOS 应用有:

TabBarController
    NavigationController1
        TableView1
            ViewController1 (Details View)
    NavigationController2
        TableView2
            ViewController2 (Details View)

行为:

期望:

执行最后一步时,我想关闭详细信息视图并查看第一个 TableView1,当切换回第二个选项卡时,我希望关闭该视图并查看 table 视图.

我已经尝试了 dismissViewControllerAnimatedpopToRootViewControllerAnimated 的不同组合,但我似乎没有弄明白。

MainTabBarController.h

@interface MainTabBarController : UITabBarController <UITabBarControllerDelegate>

MainTabBarController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    self.delegate = self;
}
...
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
    // NSLog Works fine, and displays information in the output
    NSLog (@"%@ %lu", tabBarController.selectedViewController.title, tabBarController.selectedIndex);

    // None of the lines below achieve the desired result
    [viewController.navigationController popToRootViewControllerAnimated:YES];
    [viewController dismissViewControllerAnimated:YES completion:nil];

    [tabBarController.navigationController popToRootViewControllerAnimated:YES];
    [tabBarController dismissViewControllerAnimated:YES completion:nil];
}

您可以直接设置当前在导航堆栈上的视图控制器。当在标签栏控制器中切换标签时,您所要做的就是直接设置导航控制器的 viewControllers 属性。

切换到tab1时设置NavigationController1.viewcontrollers = @[tableView1]

一种选择是使用 UITabBarControllerDelegate。监听选项卡选择的变化。基于新选项卡,获取选项卡的导航控制器并调用其 popToRootViewControllerAnimated: 方法。

根据添加到问题的代码更新:

问题在于您尝试弹出视图控制器的方式。你想要这个:

- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
    // NSLog Works fine, and displays information in the output
    NSLog (@"%@ %lu", tabBarController.selectedViewController.title, tabBarController.selectedIndex);

    // If the selected tab's root controller is a navigation controller
    // pop to the top view controller in the tab's navigation stack
    if ([viewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController *nav = (UINavigationController *)viewController;
        [nav popToRootViewControllerAnimated:NO];
    }
}

这里有一个简单的解决方案。

尝试实现UIViewContorller的以下方法

- (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing
- (void)viewDidDisappear:(BOOL)animated;  // Called after the view was dismissed, covered or otherwise hidden. Default does nothing
  1. 转到 detail-1 视图控制器并实现方法 - (void)viewWillDisappear:(BOOL)animated。 为那个控制器做一个弹出。

  2. 你应该为 detail-2 做同样的事情

这是对您有帮助的代码片段。

Appdelegate.m

@interface AppDelegate ()<UITabBarControllerDelegate>

@property(nonatomic, strong) MainTabBarController *rootTabBarController;

@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.rootTabBarController = [[MainTabBarController alloc]init];
    self.rootTabBarController.delegate = self;
    self.window.rootViewController = self.rootTabBarController;

    [self.window makeKeyAndVisible];

}

TabBarController 委托实现

-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSUInteger index = [self.rootTabBarController.viewControllers indexOfObject:viewController];
    NSLog(@"Index : %lu", (unsigned long)index);

    switch (index) {
        case 0:
            // pop other tab barcontrollers pushed or modal windows
            [self.rootTabBarController flushViewControllerStackForIndex:1];
            break;

        case 1:
            [self.rootTabBarController flushViewControllerStackForIndex:0];
            break;

        default:
            break;
    }
}

MainTabBarController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self setViewControllers:@[
                               [[UINavigationController alloc] initWithRootViewController:[[FirstViewController alloc]init]],
                               [[UINavigationController alloc] initWithRootViewController:[[SecondViewController alloc]init]]
                               ] animated:YES];
}

-(void)flushViewControllerStackForIndex:(NSUInteger )index {

    [[self.viewControllers objectAtIndex:index] popToRootViewControllerAnimated:NO];  
}

这里是示例 I 运行.

的顺序截图

这里是Sample code.

这应该可以解决您的目的,而且是正确的方法。

现在您可能需要在 flushViewControllerStackForIndex 中微调您自己的逻辑,以检查是否只有控制器被压入堆栈或压入和模态的组合。所以最好尝试在堆栈上导航 & do-a-dismiss-if-a-modaldo-a-pop-if-a-push.

希望对您有所帮助。