通常情况下,我们的控制器之间的跳转是这样的:
A.Nav -push-> B B -pop-> A
A -present-> B B -dismiss-> A
相互之间都是有层级关系和顺序的。但是,有时候项目中需要实现这样一种情况:
B.Nav -push-> X X -pop-> A
这样说可能有点抽象,大家可以打开手机看看微信,从微信的通讯录中点击某个联系人,再点击‘发送消息’按钮,直接push进入聊天室控制器,再点击聊天室控制器左上角的退出,页面是pop到’微信’页面。
怎么回事?乍一看是偷梁换柱了?实际呢,就是偷梁换柱了!
再仔细看,这些页面的跳转都是以push的效果完成的,而且非常流畅。
在介绍这种实现方法之前,请大家打消一种念头,就是利用通知,让TabBarController做调度。作者亲验,TabBarController做调度不仅达不到流畅的push效果,而且跳转过程中很突兀。
不管微信具体怎么实现,今天介绍一种有效的实现方法:
1.特别的控制器结构
一般情况下,我们最常用的控制器结构是这样的: TabBarController —> NavigationController —> viewController.而要实现上述效果,现在需要再增加一层,结构会变成这样:NavigationController —> TabBarController —> NavigationController —> viewController,如下图所示,要注意的是最外层的NavigationBar要设置成隐藏。
2. 瞒天过海
为什么要变成如此结构呢?那是因为在push的时候需要用到最外层的NavigationController,从控制器B中push到控制器X的时候, 不是[B.NavigationController pushViewController:X],而是用最外层的NavigationController来push。这样就达到了让最外层的 NavigationController作为宏观调控者。当然,要这样实现,最好做一个单例Manager,调配起来就很方便,push代码如下:
- (void)next { Item1SecondViewController *secondViewC = [[Item1SecondViewController alloc] init]; //注意:这里不是self.navigationController [[UIManager sharedInstance].tabbarViewController.navigationController pushViewController:secondViewC animated:YES]; }
这样,在视觉效果上和普通的push一样,实际是用另外一只手在操作。
3. 偷梁换柱
下来要实现从X控制器 pop出来后,停留在控制器A页面。两步:
1) 让 tabbarViewController.selectedIndex=0
2)改变里层 NavigationController的控制器堆栈
//偷梁换柱在这里…… - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; [UIManager sharedInstance].tabbarViewController.selectedIndex = 0; [self.navigationController setViewControllers:@[[UIManager sharedInstance].tabbarViewController,self]]; }
附上一组效果动画:
这样就OK啦。此方法已经在项目中使用了一段时间,是经过考验的,放心尝试吧
附demo: TabBarControllerJumpDemo