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


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

-(UIStatusBarStyle) preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

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

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

15 97

15 ответов:

я обнаружил, что если ваш ViewController находится внутри navigationController, то navigationController navigationBar.barStyle определяет стиль statusBarStyle.

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

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

ОК, вот в чем фокус. Вам нужно добавить ключ "просмотр строки состояния на основе контроллера" и установить значение No.

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

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

на 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
    }
}

The Swift 4.2 свойства были переименованы:

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

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

использование

class ViewController: UIViewController {

    // This will be called every time the ViewController appears
    // Works great for pushing & popping
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

}

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

@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. В противном случае мы просто возвращаем значение по умолчанию.

надеюсь, что это поможет всем, кто может понадобиться.

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

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

затем, в вашей информации.плист, добавить View controller-based status bar appearance и установить его в NO.

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

EDIT: вы также можете сделать это без ввода какого-либо кода: https://stackoverflow.com/a/18732865/855680

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

[self setNeedsStatusBarAppearanceUpdate];

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

можете ли вы попробовать это

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

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

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

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

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
} 

вот как я ее решал. Обычно 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
    }
}

даже со всеми ответами здесь я все еще не нашел точного решения для меня, но начал с ответа от Даниэля. То, что я в конечном итоге было:

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

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

override var preferredStatusBarStyle: UIStatusBarStyle {
     return .lightContent
}

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

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

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

добавить ниже код для вашего AppDelegate.м:

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

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

добавить UIViewControllerBasedStatusBarAppearance пара ключ-значение для вашей информации.plist и установите его в положение YES.

если ваш контроллер вида не встроен в навигационный контроллер. Скажем, MyViewController. просто добавьте код ниже в свой MyViewController.m-файл. Если ваш контроллер вида встроен в навигационный контроллер, создайте новый класс Cocoa Touch и сделайте его подклассом UINavigationController. Скажем, MyNC. Выберите Вид навигационного контроллера на раскадровке в правой панели; утилиты - > инспектор идентификации - > пользовательский класс - > класс, введите "MyNC". После связывания раскадровки Просмотр с помощью класса Cocoa Touch "MyNC", добавьте код ниже в свой MyNC.м:

- (BOOL)prefersStatusBarHidden {
    return NO;
}

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

Swift 4.2

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

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

Если вы хотите скрыть строку состояния во время splashScreen, но хотите изменить стиль на light content (StatusBarInitiallyHidden на Plist должен быть NO, чтобы скрыть строку состояния на splash), вы можете добавить это в метод didFinishLaunchingWithOptions appDelegate для изменения на lightContent.

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

swift пример

в AppDelegate.Свифт

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

    return true
}

в инфо.plist set View controller-based status bar внешний вид: нет

Если вы используете 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;
}

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

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleBlackOpaque;
}

и вызов этого метода из представления сделал загрузку, как это

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

для swift 3, в вашем UIViewController:

override var preferredStatusBarStyle : UIStatusBarStyle { return UIStatusBarStyle.lightContent }