UIStatusBarStyle PreferredStatusBarStyle не работает на iOS 7

В моем приложении iPhone, построенном с Xcode 5 для iOS 7, я установил UIViewControllerBasedStatusBarAppearance=YES в info.plist, а в моем ViewController у меня есть этот код:

-(UIStatusBarStyle) preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

Но строка состояния по-прежнему черная на черном фоне.

Я знаю, что его можно изменить в этом приложении, установив UIViewControllerBasedStatusBarAppearance=NO в info.plist, но мне действительно нужно изменить это на основе ViewController на ViewController во время выполнения.

Ответ 1

Хорошо, вот трюк. Вам нужно добавить ключ "Просмотреть строку состояния на основе контроллера" и установить значение "Нет".

Это противоречит тому, что кажется значением этого ключа, но даже если вы установите значение No, вы все равно можете изменить внешний вид строки состояния и отобразиться или нет в любом контроллере вида, Поэтому он действует как "Да", но устанавливает его в "Нет"!

Теперь я могу получить строку состояния белой или темной.

Ответ 2

Я обнаружил, что если ваш ViewController находится внутри навигационного контроллера, то навигационные контроллеры navigationBar.barStyle определяют statusBarStyle.

Настройка навигационных панелей barStyle на UIBarStyleBlackTranslucent даст белый текст строки состояния (т.е. UIStatusBarStyleLightContent), а UIBarStyleDefault предоставит черный текст строки состояния (т.е. UIStatusBarStyleDefault).

Примечание, что это применимо, даже если вы полностью измените цвет навигационных панелей через barTintColor.

Ответ 3

Я могу немного подойти к этому, но если кто-то еще ищет рабочее и проверенное решение для приложения.

@mxcl правильно описывает, почему это происходит. Чтобы исправить это, мы просто создаем расширение (или категорию в obj-c), которое переопределяет метод preferredSatusBarStyle() UINavigationController. Вот пример в Swift:

extension UINavigationController {
    public override func preferredStatusBarStyle() -> UIStatusBarStyle {
        if let rootViewController = self.viewControllers.first {
            return rootViewController.preferredStatusBarStyle()
        }
        return super.preferredStatusBarStyle()
    }
}

Этот код просто извлекает первый контроллер представления (контроллер корневого представления) и разворачивает его (в obj-c просто проверьте, что это не ноль). Если разворот успешный (не ноль), то мы захватим rootViewControllers preferredStatusBarStyle. В противном случае мы просто возвращаем значение по умолчанию.

Надеюсь, это поможет любому, кому это может понадобиться.

Ответ 4

Для preferredStatusBarStyle() для работы в UINavigationController и UITabBarController я добавлю следующий код, который получит предпочтительный стиль строки состояния из текущего видимого контроллера представления.

extension UITabBarController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return visibleViewController
    }
}

Для Swift 3 это не методы, а свойства:

extension UITabBarController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}

Ответ 5

Чтобы предоставить более подробные сведения в принятом ответе, поместите следующую строку в свой делегат приложения didFinishLaunchingWithOptions::

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

Затем в вашем Info.plist добавьте View controller-based status bar appearance и установите его в NO.

Я считаю, что это должно быть сделано, а не с контроллера навигации, если вы хотите иметь одинаковый цвет строки состояния для всего приложения. У вас могут быть экраны, которые не обязательно встроены в UINavigationController или другой подкласс UINavigationController где-то в другом месте и другие вещи.

EDIT. Вы также можете сделать это, не набрав код: fooobar.com/questions/11233/...

Ответ 6

В viewDidLoad просто напишите это

[self setNeedsStatusBarAppearanceUpdate];

просто сделайте это, и он будет работать

Можно ли попробовать, пожалуйста,

Set UIViewControllerBasedStatusBarAppearance to NO.
Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

Еще одна вещь, которую я видел в вашем вопросе, вы написали метод, подобный этому

 -(void)UIStatusBarStyle PreferredStatusBarStyle ()
        {
            return UIStatusBarStyle.LightContent;
        }

но это должно быть как

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
} 

Ответ 7

Вот как я это решил. Обычно navigationController или tabBarController - это те, которые определяют внешний вид строки состояния (скрытый, цветной и т.д.).

Итак, я закончил подклассификацию навигационного контроллера и переопределив preferredStatusBarStyle. если текущий видимый ViewContorller реализует StatusBarStyleHandler, я прошу, чтобы значение использовалось как стиль, если это не так, я просто возвращаю значение по умолчанию.

То, как вы запускаете обновление отображения строки состояния, вызывает вызов setNeedsStatusBarAppearanceUpdate, который снова запускает preferredStatusBarStyle и обновляет интерфейс в соответствии с тем, что возвращает метод

public protocol StatusBarStyleHandler {
    var preferredStatusBarStyle: UIStatusBarStyle { get }
}

public class CustomNavigationCotnroller: UINavigationController {

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        if let statusBarHandler = visibleViewController as? StatusBarStyleHandler {
            return statusBarHandler.preferredStatusBarStyle
        }

        return .default
    }
}

Затем использование

public class SomeController: UIViewController, StatusBarStyleHandler {

    private var statusBarToggle = true

    // just a sample for toggling the status bar style each time method is called
    private func toggleStatusBarColor() {
        statusBarToggle = !statusBarToggle
        setNeedsStatusBarAppearanceUpdate()
    }

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        return statusBarToggle ? .lightContent : .default
    }
}

Ответ 8

1) Одна настройка для всего проекта:

Если доступно, удалите пара ключей ключа UIViewControllerBasedStatusBarAppearance из вашего info.plist или установите NO, не удаляя его. Если он недоступен в вашем info.plist, ничего не делайте. По умолчанию это NO для этого свойства.

Добавьте нижеприведенный код в AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

2) Различные настройки для разных контроллеров просмотра:

Добавьте пару ключа-ключа UIViewControllerBasedStatusBarAppearance к вашему info.plist и установите его на YES.

Если ваш контроллер просмотра не встроен в контроллер навигации. Пусть говорят MyViewController. просто добавьте код в файл MyViewController.m. Если ваш контроллер просмотра встроен в контроллер навигации, создайте новый класс Cocoa Touch и сделайте его подклассом UINavigationController. Скажем, MyNC. Выберите пункт "Просмотр навигационного контроллера" на вашей раскадровке на правой панели; Утилиты → Identity Inspector → Custom Class → Class, введите "MyNC". После связывания Storyboard View с вашим "MyNC" Cocoa Touch Class добавьте код ниже в MyNC.m:

- (BOOL)prefersStatusBarHidden {
    return NO;
}

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

Ответ 9

Даже со всеми ответами здесь я до сих пор не нашел точного решения для меня, но начал с ответа Даниила. Я закончил с этим:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return visibleViewController?.preferredStatusBarStyle ?? .lightContent
}

в навигационных контроллерах (аналогично для вкладки, только selectedViewController). И тогда он будет уважать:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return .lightContent
}

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

Ответ 10

Если вы хотите скрыть statusBar во время splashScreen, но хотите изменить стиль для освещения контента (StatusBarInitiallyHidden на Plist должен быть НЕТ, чтобы скрыть statusBar на всплеск), вы можете добавить это в метод appDelegate didFinishLaunchingWithOptions, чтобы изменить на lightContent.

[[UIApplication sharedApplication]setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent];

Ответ 11

быстрый пример

в AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
    UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent;

    return true
}

в наборе info.plist Просмотр состояния строки состояния на основе контроллера: NO

Ответ 12

Если вы используете NavigationController, вы можете подклассифицировать NavigationController так, чтобы он консультировался с контроллером дочернего представления

//MyCustomNavigationController

- (NSUInteger)supportedInterfaceOrientations {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotate {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk shouldAutorotate];
}

- (UIStatusBarStyle)preferredStatusBarStyle {
    UIViewController *viewControllerToAsk = [self findChildVC];
    return [viewControllerToAsk preferredStatusBarStyle];
}

- (UIViewController *)findChildVC {
    return self.viewControllers.firstObject;
}

Ответ 13

Вы можете установить стиль строки состояния. Он будет похож на строку состояния, такую ​​как IOS 6 и ниже.
Вставьте эти методы в свой контроллер.

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleBlackOpaque;
}

и вызов этого метода из представления действительно загрузился следующим образом

if([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f)
    {
       [self setNeedsStatusBarAppearanceUpdate];
    }

Ответ 14

Для быстрого 3 в вашем UIViewController:

override var preferredStatusBarStyle : UIStatusBarStyle { return UIStatusBarStyle.lightContent }