Cómo cambiar la orientación del dispositivo mediante progtwigción en iOS 6

En iOS 5 podríamos cambiar la orientación del dispositivo programáticamente de esta forma:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; 

Pero en iOS 6, setOrientation está en desuso, ¿cómo puedo cambiar la orientación del dispositivo mediante progtwigción en iOS 6 ?

Aquí están mis “cinco centavos”, probados en iOS7 con ARC

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

Esto no genera una advertencia de “fuga” ya que performSelector sí lo hará.

UIAlertView : con este código, cuando abre UIAlertView durante la visualización (will / Did), se dará cuenta de que todo menos esta vista está en vertical (¿realmente manzana?). No pude forzar la orientación de la vista pero encontré que si pone un ligero retraso antes de abrir UIAlertView y luego tiene tiempo para cambiar la orientación.

Nota : Estoy publicando la semana de mi aplicación a partir del 12/09/2014 y actualizaré la publicación si se aprueba o falla.

Descubrí que la forma más fácil de forzar al dispositivo a cambiar de orientación es presentar un nuevo controlador de vista (usando presentViewController:animated:completion: donde el nuevo controlador de vista especificaba una orientación preferida particular (implementando el método -(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation )

Cuando se presenta un nuevo controlador de vista, como se esperaba, la orientación cambiará a la preferida por el nuevo controlador de vista. Entonces, la implementación más simple (¿mejor práctica?) Será incorporar todas las funcionalidades que necesitó en una orientación específica en un controlador de vista separado, y presentarlo según sea necesario. El sistema se ocupará de cambiar la orientación para usted.

Obviamente, esto puede no ser adecuado para todos los casos de uso, pero, afortunadamente, se aplica el mismo truco para forzar al dispositivo a cambiar la orientación del controlador de vista existente.

El truco es presentar un nuevo controlador de vista con la orientación preferida específica que necesita, y luego ocultarlo inmediatamente. Esto causará que la orientación cambie temporalmente cuando se presente el nuevo controlador de vista. La mejor parte es que, cuando se descarta el nuevo controlador de vista, se consulta nuevamente la preferredInterfaceOrientationForPresentation del controlador de vista original (que presenta), puede especificar la orientación final que desea aquí.

Una cosa importante a tener en cuenta aquí es también desactivar temporalmente la rotación automática en el controlador de vista original (cuando vuelve desde el controlador de vista recién presentado y descartado), de modo que cuando el usuario gira su teléfono hacia la nueva orientación, no lo hace desencadenó más rotación automática.

El siguiente código debe ilustrar mi punto, mi ejemplo obliga a la rotación a retrato, simplemente cambie en consecuencia si desea otra orientación.

Suponiendo que tiene el controlador de vista original llamado Original y un controlador de vista temporal llamado ForcePortrait

 @interface Original : UIViewController { BOOL orientationToPortrait; //should set to NO by default } @end @implementation Original - (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation { if(orientationToPortrait) { //when we manually changed, show in Portrait return UIInterfaceOrientationPortrait; } else { //before manual orientation change, we allow any orientation return self.interfaceOrientation; } } -(BOOL) shouldAutorotate { //we should 'lock' the rotation once we manually change it return !orientationToPortrait; } -(void) changeOrientationToPortrait { //Sample method to change the orientation //when called, will show (and hide) the temporary view //Original.preferredInterfaceOrientationForPresentation will be called again after this method //flag this to ensure that we tell system we prefer Portrait, whenever it asked again orientationToPortrait = YES; //presenting the following VC will cause the orientation to temporary change //when the new VC is dismissed, system will ask what is our (Original) orientation preference again ForcePortrait* forcePortrait = [[ForcePortrait alloc] init]; [self presentViewController:forcePortrait animated:NO completion:^{ [forcePortrait dismissViewControllerAnimated:NO completion:nil]; }]; } @end @interface ForcePortrait : UIViewController @end @implementation ForcePortrait - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } @end 

Esto no responde cómo cambiar la Orientación del dispositivo, sino una información adicional que podría ayudarlo.

Orientación de interfaz de interfaz de usuario iOS 6 – shouldAutorotateToInterfaceOrientation : no funciona

El método shouldAutorotateToInterfaceOrientation : NO es compatible con iOS 6. Es obsoleto. En caso de que seas un novato, que solo haya trabajado en cocoa, y te preguntes por qué tu controlador de vista está mal en iOS 6 y perfecto en iOS 5, solo debes saber que shouldAutorotateToInterfaceOrientation : ya no es compatible. Aunque puede funcionar bien con Xcode 4 a 4.3, NO funcionará en Xcode 4.5.

Apple proporciona un nuevo método para hacer esto, de una manera mucho más limpia. En su lugar, utiliza supportedInterfaceOrientations . Devuelve todas las orientaciones de interfaz compatibles con el controlador de vista, una máscara de valores de orientación de interfaz.

UIInterfaceOrientationMask Enum:

Estas constantes son bits de máscara para especificar las orientaciones de interfaz admitidas por un controlador de vista.

 typedef enum { UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait), UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft), UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight), UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown), UIInterfaceOrientationMaskLandscape = (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), UIInterfaceOrientationMaskAll = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown), UIInterfaceOrientationMaskAllButUpsideDown = (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight), } UIInterfaceOrientationMask; 

Uso de shouldAutorotateToInterfaceOrientation: método:

 -(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation); } 

Usando el método supportedInterfaceOrientations:

 -(NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskLandscapeRight; } 

Estos son los métodos agregados a UIViewController con respecto a la Orientación en iOS6

  1. UIViewController preferredInterfaceOrientationForPresentation

  2. UIViewController shouldAutorotate

  3. UIViewController supportedInterfaceOrientations

Se agregaron métodos a UIApplication con respecto a Orientation en iOS6

  1. UIApplication supportedInterfaceOrientationsForWindow:

  2. UIInterfaceOrientationMask

Prueba esto:

 #import  if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){ if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait ); } } 

Debes colocar
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
en su AppDelegate didFinishLaunchingWithOptions Method.

Luego, en cualquier lugar de su aplicación, puede obtener la orientación actual con:

 UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 

Y prueba la orientación con:

 UIInterfaceOrientationIsPortrait(orientation) UIInterfaceOrientationIsLandscape(orientation) 

como, como

 if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) { // code for landscape orientation // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft]; } else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation)) { // code for Portrait orientation // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown]; // OR [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; } 

Este código es para iOS 8 o posterior

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

Prueba esto … funcionó para mí …

 UIWindow *window = [[UIApplication sharedApplication] keyWindow]; UIView *view = [window.subviews objectAtIndex:0]; [view removeFromSuperview]; [window addSubview:view]; 

@implementation UINavigationController (autorotación)

  -(NSUInteger)supportedInterfaceOrientations { //make the check for iphone/ipad here if(IPHONE) { return UIInterfaceOrientationMaskPortrait; } else { return UIInterfaceOrientationMaskLandscape; } } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationPortrait; } - (BOOL)shouldAutorotate { return NO; } 

Una pequeña modificación a la respuesta de Bissy, si quiere evitar el uso de Runtime Library:

 if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation])) { if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) { int orientationPortrait = UIInterfaceOrientationPortrait; NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)]; NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig]; [invo setTarget:[UIDevice currentDevice]]; [invo setSelector:@selector(setOrientation:)]; [invo setArgument:&orientationPortrait atIndex:2]; [invo invoke]; } } 

Esto funciona para iOS7, forzar autorrotación a retrato.

 //In your viewController.m #import  // for autorotate viewController to portraid - (void)viewWillAppear:(BOOL)animated { UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation]; switch (orientationStatusBar) { case UIInterfaceOrientationPortrait:break; case UIInterfaceOrientationLandscapeLeft: objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); break; case UIInterfaceOrientationLandscapeRight: objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait); break; default: break; } } // this permit autorotate - (BOOL) shouldAutorotate { // this lines permit rotate if viewController is not portrait UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation]; if (orientationStatusBar != UIInterfaceOrientationPortrait) { return YES; } //this line not permit rotate is the viewController is portrait return NO; } 

NOTA: Implementé esta opción en mi aplicación, pero probablemente sería rechazada por Apple (comentario para Austin para la edición 6 de Sergey K. en octubre de 2012).

Apple hizo que cambiar la orientación del dispositivo mediante progtwigción en ios6 fuera bastante difícil (a propósito, téngalo en cuenta).

Hasta donde yo sé, la única forma de lograr lo que estás pidiendo es simular el cambio de orientación del dispositivo.

El uso de setTransform para rotar el UIView y volver a aplicar su propio marco da los resultados deseados.

 [YourView setTransform:CGAffineTransformMakeRotation(1.57)]; [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)]; 

Y cuando cambia la orientación física del dispositivo, podemos deshacer la transformación.

 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [YourView setTransform:CGAffineTransformMakeRotation(0)]; [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)]; } 
 if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) { // http://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation // http://openradar.appspot.com/radar?id=697 // [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around apple's static analysis... [[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight]; } 
 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return NO; } 

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ; } 

Esto funciona para mí en Xcode 6 y 5.

 - (BOOL)shouldAutorotate {return YES;} - (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}