在 TabBarController 上切换选项卡时关闭所有详细视图
Dismiss all Detail Views when switching Tabs on TabBarController
我的 iOS 应用有:
TabBarController
NavigationController1
TableView1
ViewController1 (Details View)
NavigationController2
TableView2
ViewController2 (Details View)
行为:
- 应用程序加载时,我看到 TableView1。
- 我 select table 中的一个项目,它带我通过显示(推送)继续详细信息视图 1.
- 我切换到底部的第二个选项卡,然后看到 TableView2。
- 我 select 一个项目,它将我带到详细信息视图 2
- 我导航回第一个选项卡,并查看详细信息视图 1
期望:
执行最后一步时,我想关闭详细信息视图并查看第一个 TableView1,当切换回第二个选项卡时,我希望关闭该视图并查看 table 视图.
我已经尝试了 dismissViewControllerAnimated
和 popToRootViewControllerAnimated
的不同组合,但我似乎没有弄明白。
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
转到 detail-1 视图控制器并实现方法 - (void)viewWillDisappear:(BOOL)animated
。
为那个控制器做一个弹出。
你应该为 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-modal 或 do-a-pop-if-a-push.
希望对您有所帮助。
我的 iOS 应用有:
TabBarController
NavigationController1
TableView1
ViewController1 (Details View)
NavigationController2
TableView2
ViewController2 (Details View)
- 应用程序加载时,我看到 TableView1。
- 我 select table 中的一个项目,它带我通过显示(推送)继续详细信息视图 1.
- 我切换到底部的第二个选项卡,然后看到 TableView2。
- 我 select 一个项目,它将我带到详细信息视图 2
- 我导航回第一个选项卡,并查看详细信息视图 1
期望:
执行最后一步时,我想关闭详细信息视图并查看第一个 TableView1,当切换回第二个选项卡时,我希望关闭该视图并查看 table 视图.
我已经尝试了 dismissViewControllerAnimated
和 popToRootViewControllerAnimated
的不同组合,但我似乎没有弄明白。
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
转到 detail-1 视图控制器并实现方法
- (void)viewWillDisappear:(BOOL)animated
。 为那个控制器做一个弹出。你应该为 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-modal 或 do-a-pop-if-a-push.
希望对您有所帮助。