ios - Preferencias de UIViewControllerStatusBarHidden no funciona
objective-c ios7 (3)
Estoy tratando de ocultar la barra de estado de uno de mis controladores de vista (cuando se muestra de forma modal). Cuando presento el controlador de vista, la barra de estado se oculta y luego se devuelve cuando se descarta.
He agregado el siguiente código al controlador de vista presentado
- (BOOL)prefersStatusBarHidden
{
return YES;
}
También he establecido las claves en el archivo Info.plist para lo siguiente:
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
Según mi entender, esto debería ser todo lo que se requiere para que esto funcione.
También estoy usando un controlador de animación personalizado para hacer la presentación que se ajusta al protocolo UIViewControllerAnimatedTransitioning
. En la animateTransition:
implementación, intenté llamar manualmente a prefersStatusBarHidden
, seguido de setNeedsStatusBarAppearanceUpdate
para garantizar que se realiza la llamada, pero la barra de estado permanece.
Cualquier idea de por qué esto está sucediendo sería apreciada. He buscado StackOverflow, pero parece que nadie ha tenido este problema, todas las respuestas aceptadas se refieren a llamar a setNeedsStatusBarAppearanceUpdate
, que ya estoy haciendo.
EDITAR - El código siguiente ahora parece FUNCIONAR como se desee
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
if (self.isPresenting) {
UIView *containerView = [transitionContext containerView];
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
toViewController.view.frame = containerView.frame;
[containerView addSubview:toViewController.view];
// Ask the presented controller whether to display the status bar
[toViewController setNeedsStatusBarAppearanceUpdate];
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
toViewController.view.alpha = 1.0f;
fromViewController.view.alpha = 0.0f;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
else {
// do the reverse
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
[UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveEaseIn animations:^{
toViewController.view.alpha = 1.0f;
fromViewController.view.alpha = 0.0f;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
// Once dismissed - ask the presenting controller if the status bar should be presented
[toViewController setNeedsStatusBarAppearanceUpdate];
}];
}
}
....
// PresentingController.m
- (BOOL)prefersStatusBarHidden
{
if (self.presentedViewController) {
return YES;
}
return NO;
}
// PresentedController.m
- (BOOL)prefersStatusBarHidden
{
return YES;
}
En iOS7, en realidad hay una nueva propiedad para UIViewController llamada modalPresentationCapturesStatusBarAppearance
. Referencia de Apple iOS.
El valor predeterminado es NO.
Cuando presente un controlador de vista llamando al método presentViewController: animado: finalización, el control de apariencia de la barra de estado se transfiere desde el controlador de vista presentado al presentado únicamente si el valor modalPresentationStyle del controlador presentado es UIModalPresentationFullScreen. Al establecer esta propiedad en SÍ, especifica la apariencia de la barra de estado de los controles del controlador de vista presentados, aunque no se muestre a pantalla completa.
El sistema ignora el valor de esta propiedad para un controlador de vista presentado a pantalla completa.
Por lo tanto, para cualquier estilo de presentación que no sea la pantalla completa normal (por ejemplo: UIModalPresentationCustom), debe establecerse si desea capturar la barra de estado. Para usar, todo lo que tiene que hacer es configurarlo en YES
en el controlador de vista que se está presentando:
toVC.modalPresentationCapturesStatusBarAppearance = YES;
Puede agregar esto a info.plist
"Ver apariencia de la barra de estado basada en el controlador" y establecer el valor en "No"
Voy a adivinar (educado, pero todavía supongo) que esto se debe a que cuando haces un controlador de vista presentado usando una transición personalizada, en iOS 7, el controlador de vista anterior todavía está allí . Por lo tanto, probablemente todavía tenga algo que decir.
Incluso puedes poner un punto de interrupción en sus prefersStatusBarHidden
para ver; Tendrás que implementarlo si no está implementado. El valor predeterminado es NO, por lo que si se consulta, eso explicaría su resultado.
Si estoy en lo cierto, necesitaría implementar las prefersStatusBarHidden
del controlador de vista prefersStatusBarHidden
para dar dos respuestas diferentes, dependiendo de si tiene o no presentedViewController
prefersStatusBarHidden
.
EDITAR Ahora he confirmado esto. Es incluso peor de lo que pensaba; en mi prueba, la segunda vista del controlador prefersStatusBarHidden
no se está llamando en absoluto. Todo está en manos del primer controlador de vista. Esto tiene sentido porque, como dije, el controlador de la primera vista nunca desaparece; con una animación de presentación personalizada, el segundo controlador de vista está subordinado al primero, porque la segunda vista puede desplazarse parcialmente sobre la primera vista.
Por lo tanto, tendrá que manejar la barra de estado por completo desde el primer controlador de vista. Puede hacer que se prefersStatusBarHidden
llamar [self setNeedsStatusBarAppearanceUpdate]
llamando [self setNeedsStatusBarAppearanceUpdate]
. Deberá dar una respuesta diferente según las circunstancias. Esto puede ser un poco complicado. Aquí hay una implementación simple, pero puede que no cubra todos los casos:
// ViewController1:
-(void)setHide:(NSNumber*)yn {
self->hide = [yn boolValue]; // a BOOL ivar
[self setNeedsStatusBarAppearanceUpdate];
}
-(BOOL)prefersStatusBarHidden {
return self->hide;
}
- (IBAction)doButton:(id)sender {
self->hide = YES;
[self setNeedsStatusBarAppearanceUpdate];
[self presentViewController:[ViewController2 new] animated:YES completion:nil];
}
// ==========
// ViewController2:
- (IBAction)doButton:(id)sender {
[self.presentingViewController setValue:NO forKey:@"hide"];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}