如何在 iOS 上检测设备的方向?

我有一个关于如何在 iOS 上检测设备方向的问题。我不需要接收更改通知,只需要当前方向本身。这似乎是一个相当简单的问题,但我还没有能够理解它。以下是我目前为止所做的工作:

UIDevice *myDevice = [UIDevice currentDevice] ;
[myDevice beginGeneratingDeviceOrientationNotifications];
UIDeviceOrientation deviceOrientation = myDevice.orientation;
BOOL isCurrentlyLandscapeView = UIDeviceOrientationIsLandscape(deviceOrientation);
[myDevice endGeneratingDeviceOrientationNotifications];

在我看来,这应该行得通。我让设备接收设备方向通知,然后询问它的方向,但是它不工作,我不知道为什么。

101847 次浏览

UIViewController有一个 interfaceOrientation属性,您可以访问该属性来查找视图控制器的当前方向。

至于你的例子,应该可以。你说没用是什么意思?与你所期望的相比,它给你带来了什么样的结果?

你解锁了设备定位的硬件锁吗? 我的 iPad1边上有一个。

真的很老套,但没有真正的解决方案。

我也遇到过同样的问题,但是我发现获取 UIDeviceLocation 并不总是一致的,所以使用以下方法:

UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;


if(orientation == 0) //Default orientation
//UI is in Default (Portrait) -- this is really a just a failsafe.
else if(orientation == UIInterfaceOrientationPortrait)
//Do something if the orientation is in Portrait
else if(orientation == UIInterfaceOrientationLandscapeLeft)
// Do something if Left
else if(orientation == UIInterfaceOrientationLandscapeRight)
//Do something if right

如果 UIViewController:

if (UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
//
}

如果 UIView:

if (UIDeviceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation))
{
//
}

UIDevice.h:

#define UIDeviceOrientationIsPortrait(orientation)  ((orientation) == UIDeviceOrientationPortrait || (orientation) == UIDeviceOrientationPortraitUpsideDown)
#define UIDeviceOrientationIsLandscape(orientation) ((orientation) == UIDeviceOrientationLandscapeLeft || (orientation) == UIDeviceOrientationLandscapeRight)

更新 :

将这段代码添加到 xxx-Prefix. pch,然后您就可以在任何地方使用它:

// check device orientation
#define dDeviceOrientation [[UIDevice currentDevice] orientation]
#define isPortrait  UIDeviceOrientationIsPortrait(dDeviceOrientation)
#define isLandscape UIDeviceOrientationIsLandscape(dDeviceOrientation)
#define isFaceUp    dDeviceOrientation == UIDeviceOrientationFaceUp   ? YES : NO
#define isFaceDown  dDeviceOrientation == UIDeviceOrientationFaceDown ? YES : NO

用途:

if (isLandscape) { NSLog(@"Landscape"); }

对于 “ UIDevice迎合”不满意,因为当 UIViewcontroller 的方向固定在一个特定的方向上时,你不会得到与设备方向相关的信息,所以正确的做法是使用 界面定位

你可以使用 “自我,界面定位”从 UIViewController 获得方向,但是当你在分解我们的代码时,你可能需要在视图控制器之外进行这种测试(自定义视图,分类...) ,所以你仍然可以通过使用 RootviewController在控制器之外的任何地方访问信息:

if (UIInterfaceOrientationIsLandscape(view.window.rootViewController.interfaceOrientation)) {
}

对于你首先要找的东西,你必须得到通知,如果方向改变! 你可以在 viewDidLoad 中设置这个东西

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];

以及每当你的设备定位改变 方向改变了时,你可以按照每个定位做任何你想做的事情

-(void)OrientationDidChange:(NSNotification*)notification
{
UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation];


if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight)
{
}
else if(Orientation==UIDeviceOrientationPortrait)
{
}
}

如果你想直接从加速度计得到 器件定位装置定位装置定位装置使用 [[UIDevice currentDevice] orientation]。但是如果您需要应用程序的当前方向(界面方向界面方向) ,请使用 [[UIApplication sharedApplication] statusBarOrientation]

有一种方法可以通过使用来自 CoreMotion 的数据来实现这一点。 这是密码:

#import <CoreMotion/CoreMotion.h>


CMMotionManager *cm=[[CMMotionManager alloc] init];
cm.deviceMotionUpdateInterval=0.2f;
[cm startDeviceMotionUpdatesToQueue:[NSOperationQueue mainQueue]
withHandler:^(CMDeviceMotion *data, NSError *error) {


if(fabs(data.gravity.x)>fabs(data.gravity.y)){
NSLog(@"LANSCAPE");
if(data.gravity.x>=0){
NSLog(@"LEFT");
}
else{
NSLog(@"RIGHT");
}


}
else{
NSLog(@"PORTRAIT");
if(data.gravity.y>=0){
NSLog(@"DOWN");
}
else{


NSLog(@"UP");
}


}


}];

以下是一些使检测更容易的 Swift 变量:

let LANDSCAPE_RIGHT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight
let LANDSCAPE_LEFT: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft
let LANDSCAPE: Bool = LANDSCAPE_LEFT || LANDSCAPE_RIGHT
let PORTRAIT_NORMAL: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.Portrait
let PORTRAIT_REVERSE: Bool = UIDevice.currentDevice().orientation == UIDeviceOrientation.PortraitUpsideDown
let PORTRAIT: Bool = PORTRAIT_REVERSE || PORTRAIT_NORMAL

在 Swift 3.0中

来获取设备定位。

/* return current device orientation.
This will return UIDeviceOrientationUnknown unless device orientation notifications are being generated.
*/
UIDevice.current.orientation

从你的应用程序获取设备定位

UIApplication.shared.statusBarOrientation

我现在的做法是:

+ (BOOL)isPortrait {
let window = UIApplication.sharedApplication.delegate.window;
if(window.rootViewController) {
let orientation =
window.rootViewController.interfaceOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
} else {
let orientation =
UIApplication.sharedApplication.statusBarOrientation;
return UIInterfaceOrientationIsPortrait(orientation);
}
}

如果由于某种原因,rootViewController 还没有安全地执行 statusBarOrient..。

最可靠的快速方法是:

public extension UIScreen {


public class var isPortrait: Bool {
UIApplication.shared.delegate?.window??.rootViewController?.interfaceOrientation.isPortrait ??
UIApplication.shared.statusBarOrientation.isPortrait
}


public class var isLandscape: Bool { !isPortrait }
}

这是我的解决方案与组合,这是相当容易使用的 SwiftUI 或常规 Swift 对象。对于这种真正的全局对象,单例对象(静态实例)比“环境”要好。

// Singleton object to keep the interface orientation (and any other global state)
class SceneContext: ObservableObject {
@Published var interfaceOrientation = UIInterfaceOrientation.portrait
static let shared = SceneContext()
}


class SceneDelegate: UIResponder, UIWindowSceneDelegate {
...
func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {
SceneContext.shared.interfaceOrientation = windowScene.interfaceOrientation
}
}


// if you want to execute some code whenever the orientation changes in SwiftUI
someView {
....
}
.onReceive(SceneContext.shared.$interfaceOrientation) { (orientation) in
// do something with the new orientation
}


// if you want to execute some code whenever the orientation changes in a regular Swift object
let pub = SceneContext.shared.$interfaceOrientation.sink(receiveValue: { (orientation) in
// do something with the new orientation
...
})