我正在编写此代码,以便对我的应用程序的布局方式进行一些更改,具体取决于它是处于横向还是纵向模式。我已经设置了应用程序以获取有关方向更改的通知,如下所示:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:NULL];
然后定义receivedRotate:
-(void) receivedRotate: (NSNotification*) notification {
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
// ... do something
}
但是,只要稍微移动设备,就会调用UIDeviceOrientationDidChangeNotification
。例如,UIDeviceOrientation可以是以下任何一种:
UIDeviceOrientationPortrait,
UIDeviceOrientationPortraitUpsideDown,
UIDeviceOrientationLandscapeLeft,
UIDeviceOrientationLandscapeRight,
UIDeviceOrientationFaceUp,
UIDeviceOrientationFaceDown
这很棒,但我只是想知道设备方向是纵向还是横向,而且我也只想在方向实际改变时运行此代码 - 从纵向到横向,反之亦然。如果他们一直转动手机,它仍处于横向模式 - 只是一种不同形式的横向模式。什么是确保我的旋转代码仅在必要时运行的理想方法?
答案 0 :(得分:2)
DeviceOrientation vs. ScreenSize vs StatusBar.isLandscape?
iOS 11,Swift 4和Xcode 9.X
无论是否使用AutoLayout
,都有多种方法可以获得正确的设备方向,并且可以在使用应用时检测旋转变化,以及在应用启动时获取正确的方向或从后台恢复后。
此解决方案在iOS 11和Xcode 9.X中运行良好
<强> 1。 UIScreen.main.bounds.size:强>
如果您只是想知道该应用是处于横向模式还是纵向模式,那么最佳起点是viewDidLoad
在发布时的rootViewController
和viewWillTransition(toSize:)
中的rootViewController
let size = UIScreen.main.bounds.size
if size.width < size.height {
print("Portrait: \(size.width) X \(size.height)")
} else {
print("Landscape: \(size.width) X \(size.height)")
}
如果您想在应用处于后台时检测轮换更改,并应以正确的方向恢复用户界面。
application:didFinishLaunchingWithOptions
这也发生在app / viewController生命周期的早期。
<强> 2。通知中心强>
如果您需要获取实际的设备方向(包括faceDown,faceUp等)。您想按如下方式添加观察者(即使您在AppDelegate的viewDidLoad
方法中执行此操作,第一个通知可能会在device = UIDevice.current
device?.beginGeneratingDeviceOrientationNotifications()
notificationCenter = Notifi`enter code here`cationCenter.default
notificationCenter?.addObserver(self, selector: #selector(deviceOrientationChanged),
name: Notification.Name("UIDeviceOrientationDidChangeNotification"),
object: nil)
执行后触发
inspectDeviceOrientation()
按如下方式添加选择器。我将其拆分为两部分,以便能够在viewWillTransition(toSize:)
@objc func deviceOrientationChanged() {
print("Orientation changed")
inspectDeviceOrientation()
}
func inspectDeviceOrientation() {
let orientation = UIDevice.current.orientation
switch UIDevice.current.orientation {
case .portrait:
print("portrait")
case .landscapeLeft:
print("landscapeLeft")
case .landscapeRight:
print("landscapeRight")
case .portraitUpsideDown:
print("portraitUpsideDown")
case .faceUp:
print("faceUp")
case .faceDown:
print("faceDown")
default: // .unknown
print("unknown")
}
if orientation.isPortrait { print("isPortrait") }
if orientation.isLandscape { print("isLandscape") }
if orientation.isFlat { print("isFlat") }
}
UIDeviceOrientationDidChangeNotification
请注意,.unknown.
可能会在发布期间多次发布,在某些情况下可能会viewDidLoad
我看到的是在{{1}之后收到第一个正确的方向通知}和viewWillAppear
方法,就在viewDidAppear
之前,甚至是applicationDidBecomeActive
方向对象将为您提供所有7种可能的方案(来自枚举UIDeviceOrientation
定义):
public enum UIDeviceOrientation : Int {
case unknown
case portrait // Device oriented vertically, home button on the bottom
case portraitUpsideDown // Device oriented vertically, home button on the top
case landscapeLeft // Device oriented horizontally, home button on the right
case landscapeRight // Device oriented horizontally, home button on the left
case faceUp // Device oriented flat, face up
case faceDown // Device oriented flat, face down
}
有趣的是,isPortrait只读Bool变量在UIDeviceOrientation
的扩展名中定义如下:
extension UIDeviceOrientation {
public var isLandscape: Bool { get }
public var isPortrait: Bool { get }
public var isFlat: Bool { get }
public var isValidInterfaceOrientation: Bool { get }
}
第3。 StatusBarOrientation 强>
UIApplication.shared.statusBarOrientation.isLandscape
这也适用于确定方向是纵向还是横向,并提供与第1点相同的结果。您可以在viewDidLoad
(适用于应用启动)和viewWillTransition(toSize:)
中进行评估,如果来自背景。但它不会向您提供有关通知的上/下,左/右,上/下的详细信息(第2点)
答案 1 :(得分:1)
我相信您所寻找的是UIInterfaceOrientation,而不是UIDeviceOrientation
。要使用它,只需在视图控制器中实现以下功能。
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
UIInterfaceOrientation currentOrientation = self.interfaceOrientation;
//
}
此枚举声明为以下
typedef enum : NSInteger {
UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
} UIInterfaceOrientation;
答案 2 :(得分:0)
将先前的方向保存在属性中,并将其与当前方向进行比较。
答案 3 :(得分:0)
@ 0x7ffffff和@Kunal Balani的答案是正确的道路,但我建议你看看UIViewController's documentation在iOS 6+应用程序上的轮换处理与在iOS 5及更早版本中处理它的方式,因为你没有提到你是否支持iOS 5(在撰写本答案的时候仍然支持iOS 5)。这将有助于解决您可能遇到的任何问题。我建议您专门查看willRotateToInterfaceOrientation:duration:
/ willAnimateRotationToInterfaceOrientation:duration:
/ didRotateFromInterfaceOrientation:
以及在轮播生命周期内调用它们的时间。
您肯定希望存储其他答案中提到的上一个方向,这样您就不会多次运行代码。
关于更具“不可知”的具体问题,关于横向与纵向的版本,UIKit's function reference包含许多相关宏,特别是UIInterfaceOrientationIsPortrait()
和UIInterfaceOrientationIsLandscape()
。