como - nfc iphone se
IOS 6 fuerza orientación del dispositivo al paisaje (13)
Di una aplicación con decir 10 controladores de vista. Yo uso el controlador de navegación para cargar / descargarlos.
Todos menos uno están en modo vertical. Supongamos que el 7 ° CV está en el paisaje. Necesito que se presente en el paisaje cuando se carga.
Sugiera una manera de forzar la orientación de vertical a horizontal en IOS 6 (y también será bueno trabajar en iOS 5).
Así es como lo estaba haciendo ANTES de IOS 6:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
UIViewController *c = [[[UIViewController alloc]init] autorelease];
[self presentModalViewController:c animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Presentar y descartar un VC modal forzaba a la aplicación a revisar su orientación, por lo que shouldAutorotateToInterfaceOrientation
estaba llamando.
Lo que he intentado en iOS 6:
- (BOOL)shouldAutorotate{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationLandscapeLeft;
}
En carga, el controlador se mantiene en el retrato. Después de rotar el dispositivo, la orientación cambia simplemente de acuerdo. Pero necesito hacer que el controlador gire automáticamente al paisaje en carga, por lo que el usuario tendrá que girar el dispositivo para ver los datos correctamente.
Otro problema: después de rotar el dispositivo de nuevo a retrato, la orientación es vertical, aunque he especificado en supportedInterfaceOrientations
solo UIInterfaceOrientationMaskLandscape
. ¿Por qué sucede?
Además, NINGUNO de los 3 métodos anteriores se están llamando.
Algunos datos (útiles):
- En mi archivo plist he especificado 3 orientaciones, todas al revés.
- El proyecto se inició en Xcode 4.3 IOS 5. Todas las clases, incluidas las xib, se crearon antes de Xcode 4.5 IOS 6, ahora utilizo la última versión.
- En el archivo plist, la barra de estado se establece en visible.
- En el archivo xib (el que quiero que esté en el paisaje), la barra de estado es "Ninguno", la orientación se establece en horizontal.
Cualquier ayuda es apreciada. Gracias.
Como alternativa, puedes hacer lo mismo con bloques:
UIViewController *viewController = [[UIViewController alloc] init];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:NO completion:^{
[self dismissViewControllerAnimated:NO completion:nil];
}];
Además, llámalo antes de empujar la nueva vista.
Creo que la mejor solución es apegarse a la documentación oficial de Apple. Entonces, de acuerdo con eso, uso los siguientes métodos y todo está funcionando muy bien en iOS 5 y 6. En mi VC anulo los siguientes métodos:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
Métodos para iOS 6, primer método devuelve máscara de orientación compatible (como su nombre indica)
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
el segundo le dice a su VC cuál es la orientación preferida de la interfaz cuando se va a mostrar el VC.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
Simplemente cambie la orientación de Portrait para que lo desee;) Esta solución funciona sin problemas, no me gusta la idea de crear macros y otras cosas, que se relacionan con esta solución simple. Espero que esto ayude...
De las notas de la versión iOS 6 :
Ahora, los contenedores iOS (como UINavigationController) no consultan a sus hijos para determinar si deben autorrotar.
¿Su rootViewController
pasa el mensaje shouldAutoRotate
por la jerarquía de ViewController
a su VC?
Esto debería funcionar, es similar a la versión anterior a iOS 6, pero con un UINavigationController
:
UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];
UIViewController
esto antes de empujar el próximo UIViewController
. UIViewController
al próximo UIViewController
empujado a mostrarse en modo vertical, incluso si el UIViewController
actual está en Paisaje (también debería funcionar para Vertical a Horizontal). Funciona en iOS 4 + 5 + 6 para mí.
He usado la siguiente solución. En el controlador de una vista que tiene una orientación diferente a todas las demás, agregué una verificación de orientación en el método prepareForSegue . Si el controlador de vista de destino necesita una orientación de interfaz diferente a la actual, se envía un mensaje que fuerza a la interfaz a rotar durante la secuencia.
#import <objc/message.h>
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if(UIDeviceOrientationIsLandscape(self.interfaceOrientation))
{
UIInterfaceOrientation destinationOrientation;
if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]])
{
UINavigationController *navController = (UINavigationController *)[segue destinationViewController];
destinationOrientation = [navController.topViewController preferredInterfaceOrientationForPresentation];
} else
{
destinationOrientation = [[segue destinationViewController] preferredInterfaceOrientationForPresentation];
}
if ( destinationOrientation == UIInterfaceOrientationPortrait )
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
{
objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
}
}
}
}
Hola chicos después de probar una gran cantidad de posibles soluciones sin éxito, salí con la siguiente solución ¡Espero que ayude !.
Preparé una receta :).
Problema: necesita cambiar la orientación de viewcontrollers usando navigationcontroller en ios 6.
Solución:
paso 1. un UIviewcontroler inicial para desencadenar modal a Landscape y Portrait UInavigationControllers como muestra la imagen ....
más profundamente en UIViewController1 necesitamos 2 acciones segues según la variable global en Appdelegate ....
-(void)viewDidAppear:(BOOL)animated{
if([globalDelegate changeOrientation]==0){
[self performSegueWithIdentifier:@"p" sender:self];
}
else{
[self performSegueWithIdentifier:@"l" sender:self];
}
}
también necesitamos un camino de vuelta a retrato y | paisaje....
- (IBAction)dimis:(id)sender {
[globalDelegate setChangeOrientation:0];
[self dismissViewControllerAnimated:NO completion:nil];
}
paso 2. el primer UIViewControllers empujado en cada NavigationController va con ...
-(NSUInteger)supportedInterfaceOrientations{
return [self.navigationController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate{
return YES;
}
paso 3. Sobrescribimos el método supportedInterfaceOrientations en la subclase de UInavigationController ....
en su CustomNavigationController tenemos .....
-(NSUInteger)supportedInterfaceOrientations{
if([self.visibleViewController isKindOfClass:[ViewController2 class]]){
return UIInterfaceOrientationMaskPortrait;
}
else{
return UIInterfaceOrientationMaskLandscape;
}
}
paso 4. En el guión gráfico o por código, establezca el indicador wantsFullScreenLayout en yes, para los controladores de navegación vertical u horizontal.
Intente realizar una transición a un UINavigationController
que use una categoría o que esté subclasificado para especificar la orientación deseada, luego realice la transición al VC deseado. Lea más here .
Lo resolví subclasificando UINavigationController y anulando las OrientacionesInterfacer soportadas del Controlador de navegación de la siguiente manera:
- (NSUInteger)supportedInterfaceOrientations
{
return [[self topViewController] supportedInterfaceOrientations];
}
Todos los controladores implementaron orientaciones de interfase compatibles con sus orientaciones deseadas.
Ok, amigos, publicaré mi solución.
Lo que tengo:
- Una aplicación basada en vista, con varios controladores de vista. (Era basado en la navegación, pero tuve que hacerlo basado en la vista, debido a problemas de orientación).
- Todos los controladores de vista son retratos, excepto uno - landscapeLeft.
Tareas:
- Uno de mis controladores de vista debe girar automáticamente a horizontal, sin importar cómo el usuario sostiene el dispositivo. Todos los demás controladores deben ser retratos, y después de abandonar el controlador de paisaje, la aplicación debe forzar la rotación para retratos, sin importar, de nuevo, cómo el usuario sostiene el dispositivo.
- Esto debe funcionar como en IOS 6.x como en IOS 5.x
¡Ir!
( Actualización eliminada de las macros sugeridas por @Ivan Vučica)
En todos los controles de vista de PORTRAIT, se anulan los métodos de autorrotación como este:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
Puede ver los 2 enfoques: uno para IOS 5 y otro para IOS 6.
Lo mismo para su controlador de vista LANDSCAPE, con algunas adiciones y cambios:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
[image_signature setImage:[self resizeImage:image_signature.image]];
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
[image_signature setImage:[self resizeImage:image_signature.image]];
return UIInterfaceOrientationMaskLandscapeLeft;
}
ATENCIÓN : para forzar la autorrotación en IOS 5 , debe agregar esto:
- (void)viewDidLoad{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];
}
De manera analógica, después de dejar el controlador LANDSCAPE, sea cual sea el controlador que cargue, debe volver a forzar la autorrotación para IOS 5, pero ahora usará UIDeviceOrientationPortrait
, cuando vaya a un controlador PORTRAIT:
- (void)viewDidLoad{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
}
Ahora lo último (y es un poco raro): tienes que cambiar la forma en que cambias de un controlador a otro, dependiendo del IOS:
Haz una clase NSObject "Schalter" ("Cambiar" del alemán).
En Schalter.h di:
#import <Foundation/Foundation.h>
@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end
En Schalter.m di:
#import "Schalter.h"
#import "AppDelegate.h"
@implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{
//adjust the frame of the new controller
CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
CGRect windowFrame = [[UIScreen mainScreen] bounds];
CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
VControllerToLoad.view.frame = firstViewFrame;
//check version and go
if (IOS_OLDER_THAN_6)
[((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
else
[((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];
//kill the previous view controller
[VControllerToRelease.view removeFromSuperview];
}
@end
AHORA, esta es la forma en que usa Schalter (supongamos que pasa del controlador de Warehouse al controlador de productos):
#import "Warehouse.h"
#import "Products.h"
@implementation Warehouse
Products *instance_to_products;
- (void)goToProducts{
instance_to_products = [[Products alloc] init];
[Schalter loadController:instance_to_products andRelease:self];
}
bla-bla-bla your methods
@end
Por supuesto, debe liberar el objeto instance_to_products
:
- (void)dealloc{
[instance_to_products release];
[super dealloc];
}
Bueno, esto es todo. No dudes en declinar, no me importa. Esto es para aquellos que buscan soluciones, no para la reputación. ¡Aclamaciones! Sava Mazare.
Tuve el mismo problema, 27 vistas en mi aplicación, de las cuales 26 en retrato y solo una en todas las orientaciones (un visor de imágenes :)). Agregar la macro en cada clase y reemplazar la navegación no era una solución con la que me sintiera cómodo ...
Por lo tanto, quería mantener la mecánica de UINavigationController en mi aplicación y no reemplazarla con otro código.
Qué hacer:
@ 1 En la aplicación delegar en el método didFinishLaunchingWithOptions
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// how the view was configured before IOS6
[self.window addSubview: navigationController.view];
[self.window makeKeyAndVisible];
}
else
{
// this is the code that will start the interface to rotate once again
[self.window setRootViewController: self.navigationController];
}
@ 2 Debido a que el navigationController solo responderá con YES para autorrotación, debemos agregar algunas limitaciones: Extienda el UINavicationController -> YourNavigationController y vincúlelo en el Interface Builder.
@ 3 Anula los "nuevos métodos molestos" del controlador de navegación.
Como esta clase es personalizada solo para esta aplicación, puede asumir la responsabilidad de sus controladores y responder en su lugar.
-(BOOL)shouldAutorotate {
if ([self.viewControllers firstObject] == YourObject)
{
return YES;
}
return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
if ([self.viewControllers firstObject] == YourObject)
{
return UIINterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
Espero que esto ayude,
Utilicé el mismo método que OP pre-ios6 (presentar y descartar un VC modal) para mostrar un controlador de vista única en modo horizontal (todos los demás en vertical). Rompió en ios6 con el paisaje VC que se muestra en el retrato.
Para solucionarlo, acabo de agregar el método preferredInterfaceOrientationForPresentation en el paisaje VC. Parece que funciona bien para os 5 y os 6 ahora.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
Vaya a su archivo Info.plist y realice el cambio
Yo tuve el mismo problema. Si desea obligar a un controlador de vista particular a aparecer en el paisaje, hágalo justo antes de insertarlo en la pila de navegación.
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (currentOrientation == UIInterfaceOrientationPortrait ||
currentOrientation == UIInterfaceOrientationPortraitUpsideDown)
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
UIViewController *vc = [[UIViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[vc release];