获取设备当前方向(应用扩展)

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");

它给了我正确的方向,但仍然没有得到,因为设备是 LandscapeLeftLandscapeRight 以及 PortraitPortraitUpsideDown强>。

仍然需要帮助。

【讨论】:

任何投我反对票的人,您是否首先实际尝试过。首先检查这个***.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
    

【讨论】:

以上是关于获取设备当前方向(应用扩展)的主要内容,如果未能解决你的问题,请参考以下文章

iphone在应用启动时获取设备方向

在 Swift 中获取设备方向

如何在纵向锁定设备时获取设备方向

即使 autoRotation 关闭,也能获取 android 设备方向

获取Android设备的方向,Sensor和SensorManager实现手机旋转角度

通过 react-native 访问移动设备的真实世界倾斜度和方向