获取设备当前方向(应用扩展)
Posted
技术标签:
【中文标题】获取设备当前方向(应用扩展)【英文标题】:Get device current orientation (App Extension) 【发布时间】:2014-08-23 12:49:24 【问题描述】:如何在应用扩展中获取设备当前方向,我尝试了以下两种方法,但都没有成功。
它总是返回 UIDeviceOrientationUnknown
[[UIDevice currentDevice] orientation]
它显示红色消息“sharedApplication”在 ios 上不可用(应用程序扩展)
[[UIApplication sharedApplication] statusBarOrientation];
我还添加了一个观察者,但它没有被调用。
[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
- (void)notification_OrientationWillChange:(NSNotification*)n
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[[n.userInfo objectForKey:UIApplicationStatusBarOrientationUserInfoKey] intValue];
if (orientation == UIInterfaceOrientationLandscapeLeft)
[self.textDocumentProxy insertText:@"Left"];
if (orientation == UIInterfaceOrientationLandscapeRight)
[self.textDocumentProxy insertText:@"Right"];
那么现在任何人如何才能获得当前的设备方向。
【问题讨论】:
你用的是哪个ios? Xcode6 beta4 与 iOS8 Apple 从 iOS 8 开始不再使用设备方向。请查看尺寸等级。 我发现这个答案很有帮助:***.com/questions/29528661/… 【参考方案1】:我有个主意!
extension UIScreen
var orientation: UIInterfaceOrientation
let point = coordinateSpace.convertPoint(CGPointZero, toCoordinateSpace: fixedCoordinateSpace)
if point == CGPointZero
return .Portrait
else if point.x != 0 && point.y != 0
return .PortraitUpsideDown
else if point.x == 0 && point.y != 0
return .LandscapeLeft
else if point.x != 0 && point.y == 0
return .LandscapeRight
else
return .Unknown
编辑:在 Swift 4 上,您可以:
extension UIScreen
var orientation: UIInterfaceOrientation
let point = coordinateSpace.convert(CGPoint.zero, to: fixedCoordinateSpace)
switch (point.x, point.y)
case (0, 0):
return .portrait
case let (x, y) where x != 0 && y != 0:
return .portraitUpsideDown
case let (0, y) where y != 0:
return .landscapeLeft
case let (x, 0) where x != 0:
return .landscapeRight
default:
return .unknown
【讨论】:
这是我见过的最好的答案。在扩展上下文和常规应用上下文中都可以完美运行,并且可以区分横向左侧和横向右侧。干得好! 天才!像魅力一样工作。 这总是给我所有方向的肖像。【参考方案2】:我在(App Extension)
中找到了一种可以像这样计算设备方向的方法- (void)viewDidLayoutSubviews
if(self.view.frame.size.width > self.view.frame.size.height)
NSLog(@"Landscape");
else
NSLog(@"Portrait");
它给了我正确的方向,但仍然没有得到,因为设备是 LandscapeLeft 或 LandscapeRight 以及 Portrait 或 PortraitUpsideDown强>。
仍然需要帮助。
【讨论】:
任何投我反对票的人,您是否首先实际尝试过。首先检查这个***.com/questions/24166878/…,并在这里解释你为什么要投票给我。 您应该使用屏幕边界而不是视图框架,因为它并不总是正确的,在我的情况下,视图宽度总是大于高度,但使用屏幕边界对我有用 CGRect r = [UIScreen mainScreen].bounds; BOOL isLandscape = r.size.width > r.size.height;【参考方案3】:如果你之前添加了这个,观察者方法将被调用:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
编辑:我使用UIApplicationDidChangeStatusBarOrientationNotification
作为观察者
我用我的方法检查:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
BOOL isPortrait = UIDeviceOrientationIsPortrait(orientation);
编辑 2- Xcode 6.2 - iOS 7 & 8
如果你想在 iOS 7 和 8 上都使用这个,上面的代码会在 iOS 7 上给你错误的结果。
所以我使用了其他东西,因为在 iOS 7 上,mainScreen 的边界永远不会改变,但在 iOS 8 上,如果方向改变就会改变。
无论 iOS 版本如何,我都有 3 个宏可以为我提供正确的屏幕宽度和高度:
#define IOS_VERSION_OLDER_THAN_8 ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
#define SCREEN_WIDTH_CALCULATED (IOS_VERSION_OLDER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.width : [[UIScreen mainScreen] bounds].size.height) : [[UIScreen mainScreen] bounds].size.width)
#define SCREEN_HEIGHT_CALCULATED (IOS_VERSION_OLDER_THAN_8 ? (UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation) ? [[UIScreen mainScreen] bounds].size.height : [[UIScreen mainScreen] bounds].size.width) : [[UIScreen mainScreen] bounds].size.height)
然后,当通知被触发时,我会像这样检查方向:
BOOL isPortrait = SCREEN_WIDTH_CALCULATED < SCREEN_HEIGHT_CALCULATED;
这适用于 iOS 7 和 iOS 8,但我没有检查旧版本的 Xcode,只有 6.2
仅当设备处于纵向或横向时才会返回,而不是所有 4 种方向类型
【讨论】:
我编辑了我的答案,也许它会对你有所帮助。我使用 Xcode 6.1 进行了测试,并且可以正常工作。 完成这个答案,还有UIDeviceOrientationDidChangeNotification
我这样做了,但是每次调用UIApplicationDidChangeStatusBarOrientationNotification
时,似乎都认为它的方向相同;即 UIDevice.currentDevice().orientation == 0。(UIDeviceOrientationDidChangeNotification
对我来说根本不起作用)
我试过这个,但它总是认为它是横向的。它不起作用:(
设备方向事件不会在应用扩展中发送【参考方案4】:
在 BroadcastExtension 中,您可以使用 sampleBuffer 来了解方向:
if let orientationAttachment = CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKey as CFString, nil) as? NSNumber
let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value)
【讨论】:
【参考方案5】:您可以查看this 库及其forks。它使用 CoreMotion 来检测设备方向,因此它可以在 App Extension 的受限环境中工作。
【讨论】:
【参考方案6】:我知道已经晚了,但是这个问题的错误在这一行:
[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
addObserver:self.view
错误,通知应附在self
上以便被调用。也适用于 iOS8。
【讨论】:
好的,我会检查这个,你确定你是在“应用程序扩展”中这样做 不,你是对的,我正在寻找标准应用程序。顺便看看这个答案,也许它也适用于 App Extension:***.com/a/24467241/1171614【参考方案7】:使用CoreMotion框架可以获取设备方向。
func startMonitorDeviceOrientation()
if motionManager.isDeviceMotionAvailable
motionManager.deviceMotionUpdateInterval = 1.0
let queue = OperationQueue()
motionManager.startDeviceMotionUpdates(to: queue) (deviceMotion, error) in
guard let x = deviceMotion?.gravity.x,
let y = deviceMotion?.gravity.y
else
return
if fabs(y) >= fabs(x)
if y >= 0
// UIDeviceOrientationPortraitUpsideDown;
print("device orientation UIDeviceOrientationPortraitUpsideDown")
else
// UIDeviceOrientationPortrait;
print("device orientation UIDeviceOrientationPortrait")
else
if x >= 0
// UIDeviceOrientationLandscapeRight;
print("device orientation UIDeviceOrientationLandscapeRight")
else
// UIDeviceOrientationLandscapeLeft;
print("device orientation UIDeviceOrientationLandscapeLeft")
else
print("Device motion is not avaliable")
【讨论】:
【参考方案8】:我无法让它在 iMessage 应用程序扩展中工作。据我所知,Apple 似乎已经默默地禁用了它。 https://forums.developer.apple.com/thread/53981
【讨论】:
【参考方案9】:方便的扩展方法,只需调用UIInterfaceOrientation.current
extension UIInterfaceOrientation
static var current: UIInterfaceOrientation
return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? UIInterfaceOrientation.portrait
【讨论】:
【参考方案10】:此代码不会为您提供确切的 UIDeviceOrientation,但您可以知道它是处于纵向还是横向模式
BOOL isLandScape = !(self.view.frame.size.width == ([[UIScreen mainScreen] bounds].size.width*([[UIScreen mainScreen] bounds].size.width<[[UIScreen mainScreen] bounds].size.height))+([[UIScreen mainScreen] bounds].size.height*([[UIScreen mainScreen] bounds].size.width>[[UIScreen mainScreen] bounds].size.height)));
【讨论】:
【参考方案11】:我已经完成了我的自定义键盘扩展,希望对你有所帮助..
为了在方向改变时更新您的自定义键盘,请覆盖 UIInputViewController 中的 viewDidLayoutSubviews。换句话说,我们可以说 viewDidLayoutSubviews 总是在旋转完成时调用。
在键盘扩展中,我们无法使用我们通常使用的传统流程:
[UIApplication sharedApplication] statusBarOrientation]
所以为了检测当前方向,我使用了以下代码: 在对象中:
if([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height)
// Portrait Orientation
else
//Landscape Orientation
在 swift4 中,你可以使用这个:
if UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height
//portrait Orientation
else
//landscape Orientation
【讨论】:
以上是关于获取设备当前方向(应用扩展)的主要内容,如果未能解决你的问题,请参考以下文章
即使 autoRotation 关闭,也能获取 android 设备方向