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

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

  1. Всегда возвращать UIDeviceOrientationUnknown

    [[UIDevice currentDevice] orientation]
    
  2. На нем отображается красное сообщение о том, что "sharedApplication" недоступно на iOS (расширение приложения)

    [[UIApplication sharedApplication] statusBarOrientation];
    
  3. Я также добавляю наблюдателя, но мне не звонят.

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

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

11 ответов

У меня есть идея!

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

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

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

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

Все еще нужна помощь.

В BroadcastExtension вы можете использовать sampleBuffer, чтобы понять ориентацию:

if let orientationAttachment =  CMGetAttachment(sampleBuffer, RPVideoSampleOrientationKey as CFString, nil) as? NSNumber 
{  
          let orientation = CGImagePropertyOrientation(rawValue: orientationAttachment.uint32Value)   
}

Метод наблюдателя будет вызван, если вы добавите это раньше:[[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 границы основного экрана никогда не изменятся, но в 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 типа ориентации

Использование CoreMotion Framework позволяет получить ориентацию устройства.

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

Удобный метод расширения, просто позвоните UIInterfaceOrientation.current

      extension UIInterfaceOrientation {
    static var current: UIInterfaceOrientation {
        return UIApplication.shared.windows.first?.windowScene?.interfaceOrientation ?? UIInterfaceOrientation.portrait
    }
}

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

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

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

Мне не удалось заставить его работать в расширении приложения iMessage. Apple, кажется, молча отключил его, насколько я могу судить. https://forums.developer.apple.com/thread/53981

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

Я сделал в моем собственном расширении клавиатуры, надеюсь, это поможет вам..

Чтобы обновить пользовательскую клавиатуру при изменении ориентации, переопределите viewDidLayoutSubviews в UIInputViewController. Другими словами, мы можем сказать, что 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
    }

Этот код не даст вам точную 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)));
Другие вопросы по тегам