通常情況下,我們的控制器之間的跳轉是這樣的:
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