PreferencesStatusBarHidden de UIViewController ne fonctionne pas

J'essaie de cacher la barre d'état de l'un de mes controllers de vue (lorsqu'il est affiché de manière modale). Lorsque je présente le controller de vue, la barre d'état doit être masquée puis renvoyée lorsqu'elle est rejetée.

J'ai ajouté le code suivant au controller de vue présenté

- (BOOL)prefersStatusBarHidden { return YES; } 

J'ai également mis les keys dans le file Info.plist à ce qui suit:

 <key>UIViewControllerBasedStatusBarAppearance</key> <true/> 

D'après ce que j'ai compris, cela devrait être tout ce qui est nécessaire pour que cela fonctionne.

J'utilise également un controller d'animation personnalisé pour faire la présentation qui est conforme au protocole UIViewControllerAnimatedTransitioning . Dans l' animateTransition: j'ai essayé d'appeler manuellement prefersStatusBarHidden , suivi de setNeedsStatusBarAppearanceUpdate pour m'assurer que l'appel est en cours, mais la barre d'état rest.

Toutes les idées pour lesquelles cela se passe seraient appréciées. J'ai recherché StackOverflow, mais il semble que personne n'a eu ce problème, toutes les réponses acceptées se réfèrent à l'appel de setNeedsStatusBarAppearanceUpdate , ce que je fais déjà.

EDIT – Le code ci-dessous semble maintenant fonctionner comme vous le souhaitez

 - (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; } 

Dans iOS7, il existe une nouvelle propriété pour UIViewController, appelée modalPresentationCapturesStatusBarAppearance . Référence Apple iOS

La valeur par défaut est NO.

Lorsque vous présentez un controller de vue en appelant la méthode presentViewController: animation: completion:, le contrôle d'apparence de la barre d'état est transféré du controller de présentation au controller de présentation présenté uniquement si la valeur modalPresentationStyle du controller présenté est UIModalPresentationFullScreen. En définissant cette propriété sur YES, vous spécifiez l'apparence de la barre d'état des controls du controller de vue présentée, même si elle n'est pas présentée en plein écran.

Le système ignore la valeur de cette propriété pour un controller de vue présenté en plein écran.

Par conséquent, pour tout présentationStyle autre que le plein écran normal (par exemple: UIModalPresentationCustom), cette option doit être définie si vous souhaitez capturer la barre d'état. Pour l'utiliser, tout ce que vous avez à faire est de le mettre à YES sur le controller de vue qui est présenté:

 toVC.modalPresentationCapturesStatusBarAppearance = YES; 

Je vais deviner (éduqué, mais toujours une supposition) que c'est parce que quand vous faites un controller de vue présenté en utilisant une transition personnalisée, dans iOS 7, l'ancien controller de vue est toujours là . Par conséquent, il a probablement encore son mot à dire.

Vous pourriez même mettre un point d'arrêt dans son prefersStatusBarHidden à voir; vous devrez l'implémenter s'il n'est pas implémenté. La valeur par défaut est NON, donc si elle est consultée, cela expliquerait votre résultat.

Si j'ai raison, vous devrez implémenter le prefersStatusBarHidden de l' ancien controller de prefersStatusBarHidden pour donner deux réponses différentes, selon qu'il possède ou non un prefersStatusBarHidden .

EDIT J'ai maintenant confirmé cela. C'est encore pire que je ne le pensais. Dans mes tests, prefersStatusBarHidden du second controller de prefersStatusBarHidden n'est pas appelé du tout. Le tout est entre les mains du premier controller de vue. Cela a du sens parce que, comme je l'ai dit, le premier controller ne disparaît jamais; Avec une animation de présentation personnalisée, le deuxième controller de vue est subordonné au premier, car la deuxième vue peut planer partiellement sur la première vue.

Ainsi, vous devrez conduire la barre d'état entièrement à partir du premier controller de vue. Vous pouvez prefersStatusBarHidden son prefersStatusBarHidden en appelant [self setNeedsStatusBarAppearanceUpdate] . Vous devrez donner une réponse différente selon les circonstances. Cela peut être un peu difficile. Voici une implémentation simple, mais elle peut ne pas couvrir tous les cas:

 // 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]; }