有這樣一個需求:項目的根視圖控制器是UITabBarController,有幾個tab對應的都是UINavigationController,其中某個UINavigationController的棧中分別有控制器a和控制器b(由控制器a push 進入 控制器b),要求只有控制器b支持旋轉。該怎麼做呢?大家都知道,在iOS 6及以後,要控制視圖的旋轉需要在最頂端的控制器中添加下面兩個回調方法
// 能否自動旋轉
- (BOOL)shouldAutorotate;
// 如果能夠旋轉,返回支持的旋轉方向
- (NSInteger)supportedInterfaceOrientations;
不同於iOS 6之前只需要在相應的視圖控制器中添加下面的回調方法- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation;
因爲項目只要支持iOS 6及以上,所以不需要額外在每個視圖控制器中做旋轉定製以支持iOS 6以前的系統。那麼解決思路就很清晰了,只要在我的最頂層的根視圖控制器中,也就是UITabBarController中進行一些判斷,如果當前的界面是控制器b的view,那麼在shouldAutorotate和supportedInterfaceOrientations中分別返回YES和支持的旋轉方向,其餘情況一律返回NO和UIInterfaceOrientationMaskPortrait。下面我們來進行具體操作,首先按需要搭建一個測試工程,工程結構如下圖所示
其中,FirstDetailViewController代表的就是需求中的控制b,它是支持除home鍵在上方向的所有方向。FirstViewController代表控制器a。最方便的解決方法就是添加一個UITabBarController的類別,在類別中添加如下代碼
#pragma mark - rotation
- (BOOL)shouldAutorotate
{
UINavigationController *nav = (UINavigationController *)self.selectedViewController;
if ([nav isEqual:[self.viewControllers objectAtIndex:0]]) {
UIViewController *vc = [nav topViewController];
if ([vc isKindOfClass:[FirstDetailViewController class]]) {
return YES;
}
}
return NO;
}
- (NSInteger)supportedInterfaceOrientations
{
UINavigationController *nav = (UINavigationController *)self.selectedViewController;
if ([nav isEqual:[self.viewControllers objectAtIndex:0]]) {
UIViewController *vc = [nav topViewController];
if ([vc isKindOfClass:[FirstDetailViewController class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
return UIInterfaceOrientationMaskPortrait;
}
到這裏爲止,已經是完成了這個需求。但是這種解決方法並不能應付所有的情況,因爲當FirstDetailViewController 在非豎屏的情況下pop的時候,你會發現FirstViewController的旋轉方向並沒有立馬旋轉回Portrait方向,而是跟FirstDetailViewController保持一致。索性項目中在FirstDetailViewController
pop之前,FirstDetailViewController一定會先返回到Portrait方向,所以就不存在任何問題。跟我的項目相似情況的如優酷手機客戶端(視頻播放界面代表了視圖控制器a),具體親們可以下載過來看看。