Получить текущую ориентацию устройства (расширение приложения)

Как получить текущую ориентацию устройства в расширении приложения, я попытался использовать два метода, но не имел успеха.

  • Он всегда возвращает 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"];
    }
    

Итак, как можно получить текущую ориентацию устройства.

Ответ 1

Я нашел способ, по которому мы могли бы вычислить нашу ориентацию устройства таким образом в (расширение приложения)

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

Он дает мне правильную ориентацию, но все же не получается, поскольку устройство LandscapeLeft или LandscapeRight, а также Портрет или PortraitUpsideDown.

По-прежнему нужна помощь.

Ответ 2

У меня появилась идея!

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
        }
    }

}

EDIT: В 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
        }
    }
}

Ответ 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 изменится, если ориентация изменится.

У меня есть 3 макроса, которые дадут мне правильный размер ширины и высоты экрана, независимо от версии iOS:

#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 типа ориентации

Ответ 4

Вы можете посмотреть эту библиотеку и forks. Он использует CoreMotion для определения ориентации устройства, поэтому он может работать в среде с ограниченным расширением приложения.

Ответ 5

Я знаю это поздно, но ошибка в этом вопросе была в этой строке:

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

addObserver:self.view неверно, уведомление должно быть прикреплено к self для вызова. Работайте также на iOS8.

Ответ 6

Этот код не даст вам точного 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)));