Как изменить UIStatusBarStyle в iOS 7 в модальных представлениях с помощью панели навигации?

Руководство по переходу iOS 7 дает хороший совет по динамическому изменению UIStatusBarStyle в UIViewController с помощью

- (UIStatusBarStyle)preferredStatusBarStyle {
     return UIStatusBarStyleDefault;
}

вместе с [self setNeedsStatusBarAppearanceUpdate];

Это отлично работает в приложении с одним представлением. Однако теперь я пытаюсь изменить UIStatusBarStyle в модальном виде на UIStatusBarStyleLightContent. Существует MainViewController, который отделяется от ModalViewController, который сам встроен в NavigationController. ModalViewController установил свой делегат в MainViewController.

Я попытался вызвать [self setNeedsStatusBarAppearanceUpdate]; в ModalViewController вместе со следующим методом в этом классе без эффекта:

// In ModalViewController.m
- (UIStatusBarStyle)preferredStatusBarStyle {
     return UIStatusBarStyleLightContent;
}

Я также попытался вызвать [self setNeedsStatusBarAppearanceUpdate]; в MainViewController в prepareForSegue: sender: методе с условиями в - (UIStatusBarStyle)preferredStatusBarStyle {}, чтобы вернуть UIStatusBarStyleLightContent, когда представлен модальный вид, но также не имеет эффектов.

Как я могу изменить UIStatusBarStyle в модальном представлении?

РЕДАКТИРОВАТЬ: Сообщение обновлено: мне нужно отметить, что ModalViewController встроен в NavigationController с NavigationBar. С NavigationBar, установленным в скрытый до вызова [self setNeedsStatusBarAppearanceUpdate]; в ModalViewController, работает нормально. Но не тогда, когда панель видна.

Ответ 1

Вам нужен ViewController, который показывает в полноэкранном режиме, чтобы вернуть соответствующую информацию о статусе. В вашем случае: NavigationController, который содержит ModalViewController, должен реализовать preferredStatusBarStyle и вернуть UIStatusBarStyleLightContent.

Вызов setNeedsStatusBarAppearanceUpdate необходим только в том случае, если значения, которые вернет диспетчер представлений, действительно изменяются. Когда контроллер представления впервые представлен, они все равно запрошены.

Ответ 2

Мы должны заметить, что не полноэкранный modalVC CAN использует modalPresentationCapturesStatusBarAppearance для управления стилем statusBar.

Любой, кто хочет узнать больше о контроле состояния, не должен игнорировать UIViewController Управление Строкой состояния.

Обновление в 2015-11-06:

И убедитесь, что вы установили UIViewControllerBasedStatusBarAppearance, описанный в iOS Keys

Ответ 3

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

Если вы используете контроллер навигации и хотите контролировать строку состояния на каждом контроллере представления, вам нужно подклассифицировать UINavigationController и реализовать preferredStatusBarStyle, чтобы он возвращал предпочтение topViewController.

Удостоверьтесь, что вы изменили ссылку на класс в сцене раскадровки из UINavigationController в ваш подкласс (например, MyNavigationController в приведенном ниже примере).

(Следующее работает для меня. Если ваше приложение основано на TabBar, вы захотите сделать что-то подобное, выполнив подкласс UITabBarController, но я этого не пробовал).

@interface MyNavigationController : UINavigationController

@end

@implementation MyNavigationController

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return self.topViewController.preferredStatusBarStyle;
}

@end

Ответ 4

Чтобы изменить строку состояния UINavigationController, встраивая ваш ViewController без подкласса UINavigationController, используйте это:

navigationController?.navigationBar.barStyle = .Black // to make the status bar text white

.Black сделает текст белым (строка состояния и название представления), в то время как .Default имеет черный заголовок и строку состояния.

Ответ 5

У меня был контроллер бокового меню/расписания (SWRevealController), который всегда является корневым контроллером для запросов строки состояния. Переопределение childViewControllerForStatusBarStyle позволяет перенаправить запрос на передний контроллер.

/**
 This view is always considered the topmost for status bar color queries.
 Pass the query along to what we're showing in front.
 */
- (UIViewController *)childViewControllerForStatusBarStyle
{
    UIViewController *front = self.frontViewController;
    if ([front isKindOfClass:[UINavigationController class]])
        return ((UINavigationController*)front).topViewController;
    else
        return front;
}

Ответ 6

Похоже, приложение отключается от statusBarStyle самого верхнего viewController. Поэтому, если вы добавите еще один viewController поверх своего текущего, теперь он получает свои реплики из нового viewController.

Ответ 7

Это работает для меня:

  • Установите View controller-based status bar appearance в NO
  • Установите стиль строки состояния на UIStatusBarStyleLightContent (просто скопируйте это значение)
  • В appDelegate используйте [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

Надеюсь, что это поможет (ref: строка состояния ios7, переходящая в черный на модальные виды?

Ответ 8

Просто найдите, если ваше приложение rootViewController необходимо переопределить - (UIStatusBarStyle) preferredStatusBarStyle метод

Ответ 9

Все вышеперечисленные работы. Однако иногда я нахожу, что это действительно боль в нижней части, чтобы пойти и изменить каждый экземпляр в Storyboard и т.д. Итак, вот что-то, что работает для меня, что также связано с подклассом.

Сначала создайте подкласс:

@interface HHNavLightColorBarController : UINavigationController

@end

@implementation HHNavLightColorBarController

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}
@end

Затем, используя магию Objective-C и немного бит < objc/runtime.h >

Если у вас есть ссылка на контроллер представления и его представление:

UINavigationController *navVC = ...; // Init in your usual way
object_setClass(navVC, [HHNavLightColorBarController class]);
[self presentViewController:nav animated:YES completion:^{
    NSLog(@"Launch Modal View Controller");
}];

Иногда это кажется немного менее навязчивым. Возможно, вы даже можете создать категорию, которая проверяет, является ли ваш kindOfClass навигационным контроллером и автоматически делает это за вас. В любом случае, ответ выше jaetzold, я просто нашел, что это удобно.