眾所周知,iOS中提供了[UIDevice currentDevice].orientation與[UIApplication sharedApplication].statusBarOrientation這兩種方式來獲取設備的屏幕方向。
其中UIDeviceOrientation包括以下幾種枚舉值
typedef NS_ENUM(NSInteger, UIDeviceOrientation) { UIDeviceOrientationUnknown, UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left UIDeviceOrientationFaceUp, // Device oriented flat, face up UIDeviceOrientationFaceDown // Device oriented flat, face down } __TVOS_PROHIBITED;
其中UIInterfaceOrientation包括以下幾種枚舉值
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationUnknown = UIDeviceOrientationUnknown, UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown, UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight, UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft } __TVOS_PROHIBITED;
可以看出UIInterfaceOrientation本質其實就是UIDeviceOrientation,但是這不是重點,說說我最近遇到的坑吧。
首先外部是一個tableview的列表頁,cell里面有視頻可以播,需求是列表頁不需要重力感應,也就說一直保持垂直方向,但是cell中的視頻點開后需要全屏,這個視頻是要有重力感應的。
這時會出現一個問題,如果我手機保持橫屏,第一次進入視頻,視頻並不會改變方向,並且UIDeviceOrientation打印出來為UIDeviceOrientationPortrait,因為我在視頻的controller里才beginGeneratingDeviceOrientationNotifications,[UIDevice currentDevice].orientation在沒有遇到方向改變的時候,他是不會更新狀態的!!!所以就造成了與實際方向不符的情況。而父頁面,也就是列表頁的UIInterfaceOrientation始終垂直,所以[UIApplication sharedApplication].statusBarOrientation也是用不了的,腫么辦!!!
於是乎,別人推薦了CMMotionManager來對方向進行判斷,CMMotionManager是從屬於Core Motion框架,利用iPhone上的重力加速計芯片來捕捉手機的各種加速值。
代碼如下:
- (void)initializeMotionManager{ motionManager = [[CMMotionManager alloc] init]; motionManager.accelerometerUpdateInterval = .2; motionManager.gyroUpdateInterval = .2; [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { if (!error) { [self outputAccelertionData:accelerometerData.acceleration]; } else{ NSLog(@"%@", error); } }]; }
- (void)outputAccelertionData:(CMAcceleration)acceleration{ UIInterfaceOrientation orientationNew; if (acceleration.x >= 0.75) { orientationNew = UIInterfaceOrientationLandscapeLeft; } else if (acceleration.x <= -0.75) { orientationNew = UIInterfaceOrientationLandscapeRight; } else if (acceleration.y <= -0.75) { orientationNew = UIInterfaceOrientationPortrait; } else if (acceleration.y >= 0.75) { orientationNew = UIInterfaceOrientationPortraitUpsideDown; } else { // Consider same as last time return; } if (orientationNew == orientationLast) return; orientationLast = orientationNew; }
這樣就可以實時的獲得當前設備的方向啦