18

How to get device current orientation in an App Extension, I have tried below two methods but no success.

  1. It always return UIDeviceOrientationUnknown

    [[UIDevice currentDevice] orientation]
    
  2. It shows red message that ‘sharedApplication’ is not available on iOS (App Extension)

    [[UIApplication sharedApplication] statusBarOrientation];
    
  3. I also add an observer but it not getting called.

    [[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"];
    }
    

So now how can anyone get current device orientation.

4

11 回答 11

19

我有个主意!

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
        }
    }
}
于 2016-05-19T16:48:05.657 回答
9

我在(App Extension)中找到了一种可以像这样计算设备方向的方法

- (void)viewDidLayoutSubviews
{
   if(self.view.frame.size.width > self.view.frame.size.height)
      NSLog(@"Landscape");
   else
      NSLog(@"Portrait");
}

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

仍然需要帮助。

于 2014-09-02T16:43:22.600 回答
6

如果你之前添加这个,观察者方法将被调用: [[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 种方向类型

于 2014-09-26T09:39:15.437 回答
6

在 BroadcastExtension 中,您可以使用 sampleBuffer 来了解方向:

if let orientationAttachment =  CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKey as CFString, nil) as? NSNumber 
{  
          let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value)   
}
于 2018-07-04T09:14:39.570 回答
0

你可以看看这个库和它的分支。它使用 CoreMotion 来检测设备方向,因此它可以在 App Extension 的受限环境中工作。

于 2014-08-27T01:27:32.217 回答
0

我知道已经晚了,但这个问题的错误在于这一行:

[[NSNotificationCenter defaultCenter] addObserver:self.view selector:@selector(notification_OrientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];

addObserver:self.view是错误的,应该附加通知self以便被调用。也适用于 iOS8。

于 2015-03-23T21:03:46.563 回答
0

我无法让它在 iMessage 应用程序扩展中工作。据我所知,Apple 似乎已经默默地禁用了它。https://forums.developer.apple.com/thread/53981

于 2018-08-10T22:25:29.027 回答
0

方便的扩展方法,只需调用UIInterfaceOrientation.current

extension UIInterfaceOrientation {
    static var current: UIInterfaceOrientation {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? UIInterfaceOrientation.portrait
    }
}
于 2021-11-19T05:43:12.787 回答
0

使用 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")
    }
}
于 2018-06-08T06:03:14.007 回答
-2

此代码不会为您提供确切的 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)));
于 2014-08-28T11:54:18.903 回答
-2

我已经完成了我的自定义键盘扩展,希望它会对你有所帮助..

为了在方向更改时更新您的自定义键盘,请覆盖 UIInputViewController 中的 viewDidLayoutSubviews。换句话说,我们可以说 viewDidLayoutSubviews 总是在旋转完成时调用。

在键盘扩展中,我们无法使用我们通常使用的传统流程:

[UIApplication sharedApplication] statusBarOrientation]

因此,为了检测当前方向,我使用了以下代码: 在 Objc 中:

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
    }
于 2018-08-14T10:35:12.520 回答