ios objective-c keyboard ios-app-extension uideviceorientation

ios - Obtener la orientación actual del dispositivo(extensión de la aplicación)



objective-c keyboard (10)

¡Tengo una idea!

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

EDITAR: En Swift 4 puedes hacer:

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

Cómo obtener la orientación actual del dispositivo en una extensión de aplicación, he intentado a continuación dos métodos pero no he tenido éxito.

  1. Siempre devuelve UIDeviceOrientationUnknown

    [[UIDevice currentDevice] orientation]

  2. Muestra un mensaje en rojo que dice que "sharedApplication" no está disponible en iOS (extensión de la aplicación)

    [[UIApplication sharedApplication] statusBarOrientation];

  3. También agrego un observador pero no me llaman.

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

Entonces, ¿cómo puede alguien obtener la orientación actual del dispositivo?


El uso del marco CoreMotion puede obtener la orientación del dispositivo.

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


En BroadcastExtension puedes usar sampleBuffer para entender la orientación:

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


Encontré una forma en la que podemos calcular la orientación de nuestro dispositivo de esta manera en (Extensión de la aplicación)

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

Me da la orientación correcta, pero aún así no lo consigo, ya que el dispositivo es LandscapeLeft o LandscapeRight , así como Portrait o PortraitUpsideDown .

Aún necesitas ayuda.


Este código no le dará la orientación UIDeviceOrientation exacta, pero podrá saber si está en modo vertical u horizontal.

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


Lo he hecho en mi extensión de teclado personalizado, espero que te ayude ..

Para actualizar su teclado personalizado cuando cambie la orientación, anule viewDidLayoutSubviews en UIInputViewController. En otra palabra, podemos decir que viewDidLayoutSubviews siempre llama cuando se realiza la rotación.

En la extensión del teclado no podemos usar el flujo tradicional como usamos habitualmente:

[UIApplication sharedApplication] statusBarOrientation]

Entonces, para detectar la orientación actual, utilicé el siguiente código: En Objc:

if([UIScreen mainScreen].bounds.size.width < [UIScreen mainScreen].bounds.size.height){ // Portrait Orientation } else{ //Landscape Orientation }

Y en swift4, puedes usar esto:

if UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height { //portrait Orientation } else { //landscape Orientation }



Podrías echar un vistazo a this biblioteca y sus forks . Utiliza CoreMotion para detectar la orientación del dispositivo, por lo que puede funcionar en el entorno restringido de App Extension.


Sé que es tarde, pero el error en esta pregunta fue en esta línea:

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

addObserver:self.view está mal, la notificación se debe adjuntar en self para que se llame. Trabaja también en iOS8.


Se llamará al método del observador si lo agrega antes: [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

Edición: uso UIApplicationDidChangeStatusBarOrientationNotification para el observador

Y en mi método lo compruebo:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; BOOL isPortrait = UIDeviceOrientationIsPortrait(orientation);

Editar 2- Xcode 6.2 - iOS 7 y 8

Parece que si desea utilizar esto en iOS 7 y 8, el código anterior le dará un resultado incorrecto en iOS 7.

Así que uso algo más porque en iOS 7 los límites de mainScreen nunca cambiarán, pero en iOS 8 cambiará si cambia la orientación.

Tengo 3 macros que me darán el tamaño correcto de ancho y alto de la pantalla, independientemente de la versión de 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)

Luego, cuando se activa la notificación, verifico la orientación de esta manera:

BOOL isPortrait = SCREEN_WIDTH_CALCULATED < SCREEN_HEIGHT_CALCULATED;

Esto funcionará en iOS 7 y iOS 8, pero no revisé versiones anteriores de Xcode, solo 6.2

Esto volverá solo si el dispositivo está en vertical u horizontal, no en los 4 tipos de orientación