iphone - iOS6: AdmiteInterfaceOrientaciones no funciona(se invoca pero la interfaz sigue girando)
objective-c (15)
Básicamente, como alguien dijo anteriormente, pero con más detalle:
- Cree un nuevo archivo que sea una subclase de UINavigationController
- Vaya a su guión gráfico y luego haga clic en el controlador de navegación, establezca su clase a la que acaba de crear.
En esta clase (archivo .m) agregue el siguiente código para que permanezca en modo retrato:
(BOOL)shouldAutorotate { return NO; } (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; }
Esto funciono para mi
En mi aplicación tengo varias vistas, algunas vistas deben admitir tanto vertical como horizontal, mientras que otras vistas solo deben admitir vertical. Así, en el resumen del proyecto, he seleccionado todas las orientaciones.
El siguiente código funcionó para deshabilitar el modo horizontal en un controlador de vista dado antes de iOS 6:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Dado que shouldAutorotateToInterfaceOrientation estaba en desuso en iOS6, he reemplazado lo anterior con:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMask.Portrait;
}
Este método se llama correctamente cuando aparece la vista (puedo establecer un punto de interrupción para garantizar esto), pero la interfaz aún gira al modo horizontal, independientemente del hecho de que estoy devolviendo la máscara solo a los modos verticales. ¿Qué estoy haciendo mal?
Parece que actualmente es imposible crear una aplicación que tenga diferentes requisitos de orientación por vista. Parece que solo se adhiere a las orientaciones especificadas en el resumen del proyecto.
En mi caso tengo UINavigationController y mi controlador de vista dentro. Tuve que crear una subclase de UINavigationController y, para admitir solo a Portrait, agregue este método:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
Así que en la subclase UINavigationController necesito verificar qué orientación es compatible con el topViewController actual.
- (NSUInteger)supportedInterfaceOrientations
{
return [[self topViewController] supportedInterfaceOrientations];
}
En primer lugar, para que su aplicación funcione solo en modo, debe devolver UIInterfaceOrientationMaskLandscape
. En caso de que quiera mantener solo el modo retrato, está haciendo las cosas correctamente.
Solo agregue la clave UISupportedInterfaceOrientations
en Info.plist y asigne los valores de orientación de la interfaz que su aplicación pretende mantener.
Además, debe devolver falso from shouldAutoRotate
en caso de que quiera evitar la rotación automática por completo. Pero le sugiero que devuelva verdadero desde aquí y especifique las orientaciones correctas en el método supportInterfaceOrientations.
Este código funcionó para mí:
-(BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
iPhone / iPad App Orientation echa un vistazo a mi propia respuesta
Intente agregar el método shouldAutorotate
La mejor forma para iOS6 específicamente se señala en "iOS6 Por Tutoriales" por el equipo de Ray Wenderlich - http://www.raywenderlich.com/ y es mejor que la subclasificación de UINavigationController para la mayoría de los casos.
Estoy usando iOS6 con un guión gráfico que incluye un conjunto UINavigationController como el controlador de vista inicial.
//AppDelegate.m: este método no está disponible antes de iOS6 desafortunadamente
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
//MyViewController.m: devuelve las orientaciones que quieras admitir para cada UIViewController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
La mejor manera que creo es hacer una Categoría en lugar de subclasificar UINavigationController
o UITabbarController
su UINavigationController + Rotation.h
#import <UIKit/UIKit.h>
@interface UINavigationController (Rotation)
@end
su UINavigationController + Rotation.m
#import "UINavigationController+Rotation.h"
@implementation UINavigationController (Rotation)
-(BOOL)shouldAutorotate
{
return [[self.viewControllers lastObject] shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}
@end
Trate de hacer que todos sus controladores importen esta categoría y esto funcione a la perfección. Incluso puede hacer que un controlador no gire y presione otro que gire.
Las respuestas aquí me indicaron la dirección correcta, aunque no pude hacer que funcionara simplemente cortando y pegando porque estoy usando UINavigationControllers dentro de un UITabBarController. Así que mi versión en AppDelegate.m tiene un aspecto similar a este, que funcionará para UITabBarControllers, UINavigationControllers o UINavigationControllers dentro de un UITabBarController. Si está utilizando otros controladores de contención personalizados, deberá agregarlos aquí (que es una especie de rollo).
- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
if ([viewController isKindOfClass:[UITabBarController class]])
{
viewController = [(UITabBarController*)viewController selectedViewController];
viewController = [self terminalViewController:viewController];
}
else if ([viewController isKindOfClass:[UINavigationController class]])
{
viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
}
return viewController;
}
- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
UIViewController* viewController = [self terminalViewController:window.rootViewController];
if (viewController)
orientations = [viewController supportedInterfaceOrientations];
return orientations;
}
Otra cosa importante que debe tener en cuenta es que debe anular supportInterfaceOrientations en sus subclases UIViewController o se configurará de forma predeterminada a lo que especificó en su lista de información.
Mi solución: subclasificado UINavigationController
y configurarlo como window.rootViewController
el controlador de vista superior de la jerarquía tomará el control de la orientación, algunos ejemplos de código: UINavigationController subclasificado
Según lo indicado por otros, si está utilizando un UINavigationController y desea personalizar varias vistas, querrá crear una subclase de UINavigationController y asegurarse de tener estos dos componentes:
@implementation CustomNavigationController
// -------------------------------------------------------------------------------
// supportedInterfaceOrientations:
// Overridden to return the supportedInterfaceOrientations of the view controller
// at the top of the navigation stack.
// By default, UIViewController (and thus, UINavigationController) always returns
// UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
// -------------------------------------------------------------------------------
// shouldAutorotate
// Overridden to return the shouldAutorotate value of the view controller
// at the top of the navigation stack.
// By default, UIViewController (and thus, UINavigationController) always returns
// YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
Entonces en cualquier vista que sea un retrato solo incluirías:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Y en cualquier punto de vista eso es todo pero al revés:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Si está utilizando UINavigationController
, debe implementar shouldAutorotate
y shouldAutorotate
en la subclase de UINavigationController
.
Estos son capaces de controlar por dos pasos, si shouldAutorotate
devuelve SÍ y luego es supportedInterfaceOrientations
shouldAutorotate
. Es una combinación muy bonita.
En este ejemplo, la mayoría de mis vistas son verticales, excepto CoverFlowView y PreviewView. La transferencia de CoverFlowView a PreviewView, PreviewView quiere seguir la rotación de CoverFlowCView.
@implementation MyNavigationController
-(BOOL)shouldAutorotate
{
if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])
return NO;
else
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])
return UIInterfaceOrientationMaskAllButUpsideDown;
else
return UIInterfaceOrientationMaskPortrait;
}
...
@end
Si está utilizando un UINavigationController como el controlador de la ventana raíz , se llamará a sus shouldAutorotate
como shouldAutorotate
y shouldAutorotate
.
Idem si está utilizando un UITabBarController , y así sucesivamente.
Por lo tanto, lo que hay que hacer es crear una subclase del controlador de navegación / barra de pestañas y anular sus métodos shouldAutorotate
& shouldAutorotate
.
Tengo la misma situación que tú. Sé que ya aceptaste una respuesta, pero pensé que agregaría otra de todos modos. Esta es la forma en que entiendo la nueva versión del sistema de rotación para trabajar. El controlador de vista raíz es el único controlador de vista que jamás se ha llamado. El razonamiento, creo, es que con los controladores de vista secundarios a menudo no tiene sentido rotar sus vistas, ya que de todos modos simplemente permanecerán dentro del marco del controlador de vista raíz.
Así que lo que sucede. En primer lugar shouldAutorotate
se llama en el controlador de vista raíz . Si se devuelve NO
entonces todo se detiene. Si se devuelve YES
, se invoca el método supportInterfaceOrientations. Si la orientación de la interfaz se confirma con este método y las orientaciones globales admitidas desde la lista de información o el delegado de la aplicación, la vista girará. Antes de la rotación, se consulta el método shouldAutomaticallyForwardRotationMethods
. Si es YES
(el valor predeterminado), todos los hijos recibirán los métodos will
y didRotateTo...
así como el padre (y, a su vez, lo enviarán a sus hijos).
Mi solución (hasta que haya una más elocuente) es consultar el último controlador de vista secundario durante el método de IninterfazInternacional supportedInterfaceOrientations
y devolver su valor. Esto me permite rotar algunas áreas mientras mantengo otras solo. Me doy cuenta de que es frágil, pero no veo otra forma que no implique complicar las cosas con llamadas a eventos, devoluciones de llamada, etc.
Una cosa que he encontrado es si tienes una aplicación antigua que todavía está funcionando
[window addSubView:viewcontroller.view]; //This is bad in so may ways but I see it all the time...
Deberá actualizarlo para:
[window setRootViewController:viewcontroller]; //since iOS 4
Una vez hecho esto, la orientación debe comenzar a funcionar de nuevo.
intente cambiar este código en AppDelegate.m
// self.window.rootViewController = self.navigationController;
[window setRootViewController:navigationController];
esta es la respuesta completa
shouldAutorotateToInterfaceOrientation no se llama en iOS 6
XD