¿Cómo puedo establecer la orientación del dispositivo mediante progtwigción en iOS7?

Estoy trabajando en una aplicación de iPad, usando autolayout, donde si el usuario habilita un cierto modo (modo "heads-up"), solo quiero soportar 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 vertical.

En el controller de vista superior, tengo lo siguiente:

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

Sobre la base de las respuestas que he visto en otros lugares, la respuesta parece ser que debería usar "application setStatusBarOrientation". Por lo tanto, en el método en el que el usuario ha seleccionado el modo "heads-up", he incluido:

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

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

De hecho, cuando estoy en modo horizontal después de ejecutar el código anterior para intentar configurar la orientación mediante progtwigción, cuando busco la aplicación "statusBarOrientation" con el siguiente código, permanece en "4" para paisaje:

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

Parecía que tal vez no se estaba activando la reproducción automática con setStatusBarOrientation, por lo que intenté agregar este código después, sin efecto:

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

Me doy count de que Apple quiere dejar la orientación del dispositivo en las manos del usuario. Sin embargo, me gustaría poder soportar el modo horizontal cuando no esté en modo "heads-up".

¿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"]; 

Rápido:

 let value = UIInterfaceOrientation.LandscapeLeft.rawValue UIDevice.currentDevice().setValue(value, forKey: "orientation") 

Lo llamo en - viewDidAppear:

Utilizar esta. Solución perfecta al problema de orientación..ios7 y anterior

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

attemptRotationToDeviceOrientation (UIViewController) llamar a attemptRotationToDeviceOrientation (UIViewController) para hacer que el sistema llame a su attemptRotationToDeviceOrientation (UIViewController) cuando la condición haya 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 debe devolver si autorizar con YES en su controller de vista

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

Pero si hace eso, su VC autorotará si el usuario rota el dispositivo … así que lo cambié a:

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

y llamo

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

para forzar una nueva orientación con un button de clic. Para volver a configurar shouldAutoRotate a NO, agregué a my rootVC

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

PS: esta solución también funciona en todos los simuladores.

La única forma que funcionó para mí es presentar el controller de vista modal ficticia.

 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 descarte el controller de vista modal.

Lo curioso es que UINavigationController hace exactamente esto cuando empuja / hace estallar controles de vista secundarios con diferentes orientaciones de interfaz compatibles (probados en iOS 6.1, 7.0).

Si desea bloquear la vista principal de su aplicación en retrato, pero desea abrir vistas emergentes en el paisaje y está utilizando tabBarController como rootViewController como yo, puede usar este código en su AppDelegate.

AppDelegate.h

 @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> @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)tabBarControllerPrefernetworkingInterfaceOrientationForPresentation:(UITabBarController *)tabBarController { return UIInterfaceOrientationPortrait; } 

Funciona muy bien.

En su viewController que desea que se muestre 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. Anote esta sección del código en AppDelegate.m

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

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

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

Agregue lo siguiente en el controller de vista raíz de la aplicación:

 class RootViewController : UIViewController { private var _interfaceOrientation: UIInterfaceOrientation = .portrait override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return UIInterfaceOrientationMask(from: _interfaceOrientation) } override var prefernetworkingInterfaceOrientationForPresentation: 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 la interfaz estén marcadas en "Información de implementación":

Orientaciones de interfaz

La orientación de la interfaz de request cambia donde las necesite:

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

El UINavigationController base debe tener la callback a continuación 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 desea solo el modo vertical, en iOS 9 (Xcode 7) puede:

  • Ir a Info.plist
  • Seleccione el elemento "Orientaciones de interfaz admitidas"
  • Eliminar "Paisaje (button de inicio de la izquierda)" y "Paisaje (button de inicio de la derecha)"

introduzca la descripción de la imagen aquí

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

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

  • Habilitación de todas las orientaciones en Info.plist del proyecto.

introduzca la descripción de la imagen aquí

  • Deshabilitar la orientación en aquellos ViewControllers donde necesito que el dispositivo no gire, como en la pantalla de inicio de session 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 debería permanecer en modo vertical, simplemente agregue esta anulación y ya está configurado.

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

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

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

C objective

 - (void)flipOrientation { NSNumber *value; UIInterfaceOrientation currentOrientation = [[UIApplication shanetworkingApplication] 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.shanetworking.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() } 

Intente esto junto con su código.

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

una vez que el usuario selecciona cualquier opción, entonces llama a este método porque el usuario puede estar en modo horizontal y luego puede configurar solo el modo vertical en el mismo controller de vista para que la vista automáticamente se mueva al modo vertical, de modo que en ese button actúe llame a esto

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