Подтвердить что ты не робот

UIViewController prefersStatusBarHidden не работает

Я пытаюсь скрыть строку состояния, чтобы один из моих контроллеров был скрыт (при отображении модально). Когда я представляю контроллер представления, строка состояния должна быть скрыта, а затем возвращена после отклонения.

Я добавил следующий код к представленному контроллеру представления

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

Я также установил ключи в файле Info.plist следующим образом:

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

Из моего понимания это должно быть все, что требуется для выполнения этой работы.

Я также использую пользовательский контроллер анимации, чтобы выполнить презентацию, которая соответствует протоколу UIViewControllerAnimatedTransitioning. В реализации animateTransition: я попытался вручную вызвать prefersStatusBarHidden, а затем setNeedsStatusBarAppearanceUpdate, чтобы убедиться, что вызов выполнен, но строка состояния остается.

Любые идеи, почему это происходит, будут оценены. Я искал StackOverflow, но, похоже, никто не имел этой проблемы, все принятые ответы относятся к вызову setNeedsStatusBarAppearanceUpdate, который я уже делаю.

EDIT. Теперь код ниже выглядит как РАБОТА

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

Ответ 1

В iOS7 фактически существует новое свойство для UIViewController, называемое modalPresentationCapturesStatusBarAppearance. ссылка Apple iOS.

Значение по умолчанию: NO.

Когда вы представляете контроллер представления, вызывая метод currentViewController: анимированный: завершение:, управление представлением строки состояния передается из представления на представленный контроллер представления только в том случае, если представленные значения контроллеров modalPresentationStyle имеют значение UIModalPresentationFullScreen. Установив для этого свойства значение "ДА", вы указываете, что представленный элемент управления представлением контроля отображает состояние строки состояния, даже если представлен не полноэкранный режим.

Система игнорирует значение этого свойства для контроллера представления, представленного в полноэкранном режиме.

Следовательно, для любого представленияStyle, отличного от обычного полноэкранного (например: UIModalPresentationCustom), этот должен быть установлен, если вы хотите захватить строку состояния. Для использования все, что вам нужно сделать, - установить на YES на контроллере представления:

toVC.modalPresentationCapturesStatusBarAppearance = YES;

Ответ 2

Я собираюсь угадать (образованный, но все же догадываться), что это связано с тем, что когда вы делаете представленный контроллер представлений с использованием настраиваемого перехода, в iOS 7 старый контроллер просмотра все еще существует. Поэтому он, вероятно, все еще получает ответ.

Вы даже можете поставить точку останова в prefersStatusBarHidden, чтобы увидеть; вам придется реализовать его, если он не реализован. По умолчанию НЕТ, поэтому, если с ним будут проведены консультации, это объяснит ваш результат.

Если я прав, вам нужно будет реализовать старый контроллер представления prefersStatusBarHidden, чтобы дать два разных ответа, в зависимости от того, имеет ли он presentedViewController или нет.

EDIT Я подтвердил это. Это еще хуже, чем я думал; в моем тестировании второй контроллер представления prefersStatusBarHidden вообще не вызывается. Все это находится в руках первого контроллера. Это имеет смысл, потому что, как я уже сказал, первый контроллер просмотра никогда не уходит; с персонализированной анимацией представления, второй контроллер представления подчинен первому, поскольку второй вид может частично нависать над первым представлением.

Таким образом, вам придется полностью управлять статусной строкой с первого контроллера представления. Вы можете вызвать его prefersStatusBarHidden, вызвав [self setNeedsStatusBarAppearanceUpdate]. В зависимости от обстоятельств вам нужно будет дать другой ответ. Это может быть немного сложно. Здесь простая реализация, но она может не охватывать все случаи:

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

Ответ 3

Вы можете добавить это в info.plist

"Просмотреть внешний вид строки состояния на основе контроллера" и установить значение "Нет"

Ответ 4

Если он не работает и ваш UIViewController является дочерним в UINavigationController, то этот код может быть решением для вас.

open override var prefersStatusBarHidden: Bool {
    return topViewController?.prefersStatusBarHidden ?? super.prefersStatusBarHidden
}

По сути, UINavigationController использует свое собственное значение prefersStatusBarHidden, но в моем случае я хотел перезаписать его своим свойством контроллера вида сверху в иерархии.