¿Cómo configuro programáticamente la orientación del dispositivo en iOS7?

Estoy trabajando en una aplicación para iPad, usando el autolayout, donde si el usuario habilita un cierto modo (modo “heads-up”), quiero apoyar solo la orientación vertical (o retrato al revés), y además, si el dispositivo está en paisaje, me gustaría cambiar automáticamente al modo retrato.

En el controlador de vista superior, tengo lo siguiente:

- (NSUInteger) supportedInterfaceOrientations { if (self.modeHeadsUp) { return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown; } else { return UIInterfaceOrientationMaskAll; } } - (BOOL) shouldAutorotate { return TRUE; } 

En base a las respuestas que he visto en otro lugar aquí, la respuesta parece ser que debería usar “application setStatusBarOrientation”. Por lo tanto, en el método donde el usuario ha seleccionado el modo “mano a mano”, he incluido:

  UIApplication *application = [UIApplication sharedApplication]; [application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES]; 

Sin embargo, esto simplemente no parece hacer nada. Aunque puedo mover físicamente el dispositivo para que gire en vertical, no lo hace automáticamente.

De hecho, cuando estoy en modo apaisado después de ejecutar el código anterior para intentar establecer la orientación programáticamente, cuando consulto la aplicación “statusBarOrientation” con el siguiente código, permanece en “4” para el paisaje:

 UIApplication *application = [UIApplication sharedApplication]; int orientation = [application statusBarOrientation]; self.movesTextView.text = [NSString stringWithFormat:@"ORIENTATION %d", orientation]; 

Parecía que quizás la función de autoalimentación no se activaba con setStatusBarOrientation, así que intenté agregar este código después, sin ningún efecto:

  [super updateViewConstraints]; [self.view updateConstraints]; 

Me doy cuenta de que Apple quiere dejar la orientación del dispositivo en manos del usuario. Sin embargo, me gustaría ser compatible con el modo paisaje cuando no esté en el modo “mano a mano”.

¿Me estoy perdiendo algo para poder forzar el cambio de orientación?

Para iOS 7 y 8:

C objective:

 NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

Swift 3+:

 let value = UIInterfaceOrientation.landscapeLeft.rawValue UIDevice.current.setValue(value, forKey: "orientation") 

Lo llamo in - viewDidAppear:

Utilizar esta. Solución perfecta para el problema de orientación..ios7 y anteriores

 [[UIDevice currentDevice] setValue: [NSNumber numberWithInteger: UIInterfaceOrientationPortrait] forKey:@"orientation"]; 

attemptRotationToDeviceOrientation (UIViewController) llamar a attemptRotationToDeviceOrientation (UIViewController) para que el sistema llame a su supportedInterfaceOrientations cuando la condición ha cambiado.

Esto funciona para mí en Xcode 6 y 5.

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return (UIInterfaceOrientationMaskPortrait); } 
 NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 

funciona pero tienes que devolver shouldAutorotate con YES en tu controlador de vista

 - (BOOL)shouldAutorotate { return self.shouldAutoRotate; } 

Pero si lo haces, tu VC se autorrregará si el usuario gira el dispositivo … así que lo cambié a:

 @property (nonatomic, assign) BOOL shouldAutoRotate; - (BOOL)shouldAutorotate { return self.shouldAutoRotate; } 

y yo llamo

 - (void)swithInterfaceOrientation:(UIInterfaceOrientation)orientation { self.rootVC.shouldAutoRotate = YES; NSNumber *value = [NSNumber numberWithInt: orientation]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; } 

forzar una nueva orientación con un clic de botón. Para volver atrás debeAutoRotate a NO, agregué a mi rootVC

 - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { self.shouldAutoRotate = NO; } 

PD: Esta solución también funciona en todos los simuladores.

La única forma que funcionó para mí es la presentación del controlador de vista modal ficticio.

 UIViewController* dummyVC = [[UIViewController alloc] init]; dummyVC.view = [[UIView alloc] init]; [self presentModalViewController:dummyVC animated:NO]; [self dismissModalViewControllerAnimated:NO]; 

A su VC se le solicitarán orientaciones de interfaz actualizadas cuando se desactive el controlador de vista modal.

Lo curioso es que UINavigationController hace exactamente esto al presionar / hacer saltar los controladores de vista infantil con diferentes orientaciones de interfaz compatibles (probado en iOS 6.1, 7.0).

Esta solución le permite forzar una cierta orientación de interfaz, anulando temporalmente el valor de UIDevice.current.orientation y luego solicitando al sistema que gire la interfaz para que coincida con la rotación del dispositivo:

Importante: este es un truco y podría dejar de funcionar en cualquier momento

Agregue lo siguiente en el controlador de vista raíz de su aplicación:

 class RootViewController : UIViewController { private var _interfaceOrientation: UIInterfaceOrientation = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) } override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { return _interfaceOrientation } override func viewDidLoad() { super.viewDidLoad() // Register for notifications NotificationCenter.default.addObserver(self, selector: #selector(RootViewController.handleInterfaceOrientationChangeRequestedNotification(_:)), name: .interfaceOrientationChangeRequested, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } func handleInterfaceOrientationChangeRequestedNotification(_ notification: Notification) { guard let interfaceOrientation = notification.object as? UIInterfaceOrientation else { return } _interfaceOrientation = interfaceOrientation // Set device orientation // Important: // • Passing a UIDeviceOrientation here doesn't work, but passing a UIInterfaceOrientation does // • This is a hack, and could stop working at any moment UIDevice.current.setValue(interfaceOrientation.rawValue, forKey: "orientation") // Rotate the interface to the device orientation we just set UIViewController.attemptRotationToDeviceOrientation() } } private extension UIInterfaceOrientationMask { init(from interfaceOrientation: UIInterfaceOrientation) { switch interfaceOrientation { case .portrait: self = .portrait case .landscapeLeft: self = .landscapeLeft case .landscapeRight: self = .landscapeRight case .portraitUpsideDown: self = .portraitUpsideDown case .unknown: self = .portrait } } } extension Notification.Name { static let interfaceOrientationChangeRequested = Notification.Name(rawValue: "interfaceOrientationChangeRequested") } 

Asegúrese de que todas las orientaciones de interfaz estén marcadas en “Información de implementación”:

Orientaciones de interfaz

Solicite cambios de orientación de interfaz donde los necesite:

 NotificationCenter.default.post(name: .interfaceOrientationChangeRequested, object: UIInterfaceOrientation.landscapeRight) 

Si desea bloquear la vista principal de su aplicación en vertical, pero quiere abrir vistas emergentes en horizontal, y está usando tabBarController como rootViewController como soy, puede usar este código en su AppDelegate.

AppDelegate.h

 @interface AppDelegate : UIResponder  @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UITabBarController *tabBarController; @end 

AppDelegate.m

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Create a tab bar and set it as root view for the application self.tabBarController = [[UITabBarController alloc] init]; self.tabBarController.delegate = self; self.window.rootViewController = self.tabBarController; ... } - (NSUInteger)tabBarControllerSupportedInterfaceOrientations:(UITabBarController *)tabBarController { return UIInterfaceOrientationMaskPortrait; } - (UIInterfaceOrientation)tabBarControllerPreferredInterfaceOrientationForPresentation:(UITabBarController *)tabBarController { return UIInterfaceOrientationPortrait; } 

Funciona muy bien.

En su viewController que desea que se presente en el paisaje, simplemente use lo siguiente:

 - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } - (BOOL)shouldAutorotate { return YES; } 
  1. Agregue esta statement a AppDelegate.h

     //whether to allow cross screen marker @property (nonatomic, assign) allowRotation BOOL; 
  2. Escriba esta sección de código en AppDelegate.m

     - (UIInterfaceOrientationMask) application: (UIApplication *) supportedInterfaceOrientationsForWindow: application (UIWindow *) window { If (self.allowRotation) { UIInterfaceOrientationMaskAll return; } UIInterfaceOrientationMaskPortrait return; } 
  3. Cambiar la propiedad allowRotation de la aplicación delegada

El UINavigationController base debe tener la callback siguiente para que los elementos secundarios puedan decidir qué orientación desean.

 -(NSUInteger)supportedInterfaceOrientations { UIViewController *topVC = self.topViewController; return topVC.supportedInterfaceOrientations; } -(BOOL)shouldAutorotate { UIViewController *topVC = self.topViewController; return [topVC shouldAutorotate]; } 

Si solo desea el modo de retrato, en iOS 9 (Xcode 7) puede:

  • Ir a Info.plist
  • Seleccione el elemento “Orientaciones de interfaz admitidas”
  • Eliminar “Paisaje (botón de inicio a la izquierda)” y “Paisaje (botón de inicio a la derecha)”

enter image description here

Estaba en un problema similar al tuyo. Necesito bloquear la orientación del dispositivo para algunas pantallas (como Iniciar sesión) y permitir la rotación en otras.

Después de algunos cambios y siguiendo algunas respuestas a continuación, lo hice por:

  • Habilitando todas las orientaciones en Info.plist del Proyecto.

enter image description here

  • Desactivar la orientación en esos ViewControllers donde necesito que el dispositivo no gire, como en la pantalla de inicio de sesión en mi caso. Necesitaba anular el método shouldAutorotate en este VC:

-(BOOL)shouldAutorotate{ return NO; }

Espero que esto funcione para usted.

Si tiene un UIViewController que debe permanecer en modo vertical, simplemente agregue esta anulación y ya está todo listo.

 override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { return UIInterfaceOrientationMask.Portrait } 

La mejor parte es que no hay animación cuando se muestra esta vista, simplemente ya está en la orientación correcta.

aquí está un ejemplo de TRABAJO COMPLETO para iOS 7, 8, 9, 10 cómo cambiar la orientación de la aplicación a su opuesto actual

C objective

 - (void)flipOrientation { NSNumber *value; UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation]; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientationPortrait) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortraitUpsideDown]; } else //if(currentOrientation == UIInterfaceOrientationPortraitUpsideDown) { value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; } } else { if(currentOrientation == UIInterfaceOrientationLandscapeRight) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft]; } else //if(currentOrientation == UIInterfaceOrientationLandscapeLeft) { value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; } } [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; [UIViewController attemptRotationToDeviceOrientation]; } 

Swift 3

 func flipOrientation() -> Void { let currentOrientation : UIInterfaceOrientation = UIApplication.shared.statusBarOrientation var value : Int = 0; if(UIInterfaceOrientationIsPortrait(currentOrientation)) { if(currentOrientation == UIInterfaceOrientation.portrait) { value = UIInterfaceOrientation.portraitUpsideDown.rawValue } else //if(currentOrientation == UIInterfaceOrientation.portraitUpsideDown) { value = UIInterfaceOrientation.portrait.rawValue } } else { if(currentOrientation == UIInterfaceOrientation.landscapeRight) { value = UIInterfaceOrientation.landscapeLeft.rawValue } else //if(currentOrientation == UIInterfaceOrientation.landscapeLeft) { value = UIInterfaceOrientation.landscapeRight.rawValue } } UIDevice.current.setValue(value, forKey: "orientation") UIViewController.attemptRotationToDeviceOrientation() } 

Prueba esto junto con tu código.

 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

una vez que el usuario seleccione cualquier opción, llame a este método porque el usuario puede estar en modo horizontal y luego puede configurar solo el modo vertical en el mismo controlador de vista para que la vista automática se mueva al modo vertical, de modo que en ese botón actíquelo.

 -(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration 

Esto me funcionó perfectamente …

 NSNumber *value = [NSNumber numberWithInt:UIDeviceOrientationPortrait]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"];