(UIDeviceOrientation)(UIInterfaceOrientation)注意:
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft兩者是相反的,經過測試發現: 在【General】 -->【Deployment Info】-->【Device Orientation】勾選Landscape Right 設備支持的方向是聽筒在左,Home鍵在右的方向,而 此時打印的device方向是UIDeviceOrientationLandscapeLeft 打印的Interface的方向是UIInterfaceOrientationLandscapeLeft
這個是ios6之后新增的一組枚舉值,使用組合時更加方便,具體兩者有什么區別,暫時還沒搞清楚,使用時根據返回值類型選擇正確的格式,避免可能出現的bug
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),} [UIDevice currentDevice].orientation @PRoperty(nonatomic,readonly) UIDeviceOrientation orientation;       // return current device orientation.  this will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.  如果關閉了系統的橫豎屏切換開關,即系統層級只允許豎屏時,再通過上述方式獲取到的設備方向將是UIDeviceOrientationPortrait。   - 界面      self.interfaceOrientation ios之后8廢除         [UIapplication sharedApplication].statusBarOrientation   
打開【General】 -->【Deployment Info】-->【Device Orientation】 可以發現Xcode默認支持的設備方向有Portrait、Landscape Left、Landscape Right,Upside Down 方向是不支持的。 
此處我們把Upside Down勾中,發現在ipad中已經默認支持四個方向,但在iPhone中UpsideDown方向不會發生變化。
原因:   **此處是設置支持的設備方向,界面看到的方向是Interface的方向,此時在全部選中的情況下(UIInterfaceOrientationMask)supportedInterfaceOrientations方法,   iPad默認返回UIInterfaceorientationMaskAll,   iPhone默認返回UIInterfaceOrientationMaskAllButUpsideDown。   iPhone若要支持UpsideDown,需重寫(UIInterfaceOrientationMask)supportedInterfaceOrientations**
具體設置方法,下面再詳細介紹。
打開【Info】 -->【Custom iOS Target Properties】-->【Supported interface orientations】 默認和【General】 -->【Deployment Info】-->【Device Orientation】值一樣

Device的方向是我們是通過改變握持方向去改變的,不是代碼能夠改變的,所以這里對Device Orientation只有Support的概念。通過【General】 -->【Deployment Info】-->【Device Orientation】設置。
 如圖所示,可以通過修改
 如圖所示,可以通過修改Info.plist里的UISupportedInterfaceOrientations的屬性修改Interface的SupportOrientation。

設置Interface的界面的Orientation,plist里并沒有直接給出,需要我們自行添加,添加方式和UISupportedInterfaceOrientations相同。
注意:   在【General】 -->【Deployment Info】-->【Device Orientation】設置設備支持方向時,plist里的Supported interface orientations會根據設備方向自動添加Interface的支持方向。如不需要某方向的UISupportedInterfaceOrientations,可以在Info.plist里手動修改,該修改并不會影響Device的SupportOrientation。
iOS6的UIApplicationDelegate提供了下述方法,能夠指定UIWindow中的界面的屏幕方向:
該方法默認值為Info.plist中配置的Supported interface orientations項的值。
三個方法
//Interface的方向是否會跟隨設備方向自動旋轉,如果返回NO,后兩個方法不會再調用- (BOOL)shouldAutorotate { return YES;}//返回直接支持的方向- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskPortrait;}//返回最優先顯示的屏幕方向- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait;}解釋   1.第二個方法,在iPad上的默認返回值是UIInterfaceOrientationMaskAll,iPhone上的默認返回值是UIInterfaceOrientationMaskAllButUpsideDown;   2.在前面DeviceOrientation即使全部勾選了,若要iPhone支持UpsideDown,也要在viewcontroller里重寫第二個方法。返回包含UpsideDown的方向;   3.第三個方法,比如同時支持Portrait和Landscape方向,但想優先顯示Landscape方向,那軟件啟動的時候就會先顯示Landscape,在手機切換旋轉方向的時候仍然可以在Portrait和Landscape之間切換;
這三個方法是iOS6之后才有的,有個特點是只在兩種情況下才生效
1.當前viewController是window的rootViewController。   2.當前viewController是modal模式的,即此viewController是調用presentModalViewController而顯示出來的.
在以上兩種情況中,supportedInterfaceOrientations的方法會作用于當前的viewController和所有的childViewController,如果不是以上的兩種情況下的viewController,UIKit不會執行上述方法。
**這三種方法控制規則的交集就是一個viewController的最終支持的方向;   如果最終的交集為空,在iOS6以后會拋出UIApplicationInvalidInterfaceOrientationException崩潰異常。**
在實際的項目需求過程中,往往是有一些需要固定方向,有些需要支持旋轉適應的。剛才上面提到過,通過UIViewController的三個方法設置Orientation時,只有在是window的rootViewController或者modal模式下才生效。單獨設置某個viewController并沒有效果。這樣就給我們帶來了一些麻煩,通過調查研究,大概有這么幾種解決方案。
如:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations{ if([[self topViewController] isKindOfClass:[subViewController class]]) return UIInterfaceOrientationMaskAllButUpsideDown; else return UIInterfaceOrientationMaskPortrait;}或者在UINavigationController或UITabBarController里重寫
UINavigationController 使用self.topViewController   UITabBarController 使用self.selectedViewController
然后在viewController重寫這三個方法,這樣就巧妙的繞開了UIKit只調用rootViewController的方法的規則. 把決定權交給了當前正在顯示的viewController. 
但是   這樣是可以在當前viewController達到預期效果,但是在返回上一頁時,或者在當前頁面不不支持的方向的上一頁進來時,不能立即達到預期狀態,需要設備方向更換一次才能恢復正常。
解決方案:
#pragma mark -UITabBarControllerDelegate- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { [self presentViewController:[UIViewController new] animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];}#pragma mark -UINavigationControllerDelegate- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated { [self presentViewController:[UIViewController new] animated:NO completion:^{ [self dismissViewControllerAnimated:NO completion:nil]; }];}這樣就會觸發-(BOOL)shouldAutorotate方法和 -(UIInterfaceOrientationMask)supportedInterfaceOrientations方法,但是會閃一下,依然不完美。
這種方法不適用rootViewController是UITabBarController的, 不推薦使用。
代碼如下:
//設置statusBar[[UIApplication sharedApplication] setStatusBarOrientation:orientation];//計算旋轉角度float arch;if (orientation == UIInterfaceOrientationLandscapeLeft) arch = -M_PI_2;else if (orientation == UIInterfaceOrientationLandscapeRight) arch = M_PI_2;else arch = 0;//對navigationController.view 進行強制旋轉self.navigationController.view.transform = CGAffineTransformMakeRotation(arch);self.navigationController.view.bounds = UIInterfaceOrientationIsLandscape(orientation) ? CGRectMake(0, 0, SCREEN_HEIGHT, SCREEN_WIDTH) : initialBounds;statusBar不會自己旋轉,這里要首先設置statusBar的方向。ios9后setStatusBarOrientation方法廢除,在ios10中測試,不設置StatusBarOrientation會自動調整  我們這里選擇的是self.navigationController進行旋轉,當然也可以是self.view或者self.window,都可以,最好是全屏的view.  我們需要顯示的設置bounds,UIKit并不知道你偷偷摸摸干了這些事情。  -(BOOL)shouldAutorotate方法,應返回NO  在iOS 9 之后橫屏時,狀態欄會消失。
解決方法:確保Info.plist中的【View controller-based status bar appearance】為YES,然后重寫viewController的- (BOOL)prefersstatusBarHidden,返回值是NO。詳細參考iOS-UIStatusBar詳細總結
setOrientation 在iOS3以后變為私有方法了,不能直接去調用此方法,否則后果就是被打回。 不能直接調用,但是可以間接的去調用,下面的方法就是利用 KVO機制去間接調用,多次驗證不會被打回,放心!
方法見4.3
參考文章: iOS屏幕旋轉學習筆記 [iOS]Orientation 想怎么轉就怎么轉 iOS 知識小集(橫豎屏切換) iOS強制改變物理設備方向的進階方法
| 
 
 | 
新聞熱點
疑難解答