preferredStatusBarStyle не называется
я следовал этой теме переопределить -preferredStatusBarStyle
, но это не называется.
Есть ли какие-либо варианты, которые я могу изменить, чтобы включить его? (Я использую XIBs в своем проекте.)
21 ответов
возможные причины
у меня была та же проблема, и я понял, что это происходит, потому что я не устанавливал контроллер корневого представления в окне приложения.
на UIViewController
в котором я реализовал preferredStatusBarStyle
использовался UITabBarController
, который контролировал внешний вид видов на экране.
когда я устанавливаю контроллер корневого вида, чтобы указать на это UITabBarController
строка состояния начали работать правильно, как и ожидалось (и preferredStatusBarStyle
метод был вызван).
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
... // other view controller loading/setup code
self.window.rootViewController = rootTabBarController;
[self.window makeKeyAndVisible];
return YES;
}
альтернативный метод (устаревший в iOS 9)
кроме того, вы можете вызвать один из следующих методов, в зависимости от вашего вида контроллеров, в зависимости от его цвета фона, вместо того, чтобы использовать setNeedsStatusBarAppearanceUpdate
:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
или
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
обратите внимание, что вам также понадобится установить UIViewControllerBasedStatusBarAppearance
to NO
в файл plist, если вы используете этот метод.
для тех, кто использует UINavigationController:
на UINavigationController
не на preferredStatusBarStyle
вызовы его дочерних контроллеров представления. Вместо этого он управляет своим собственным состоянием - как и должно быть, он рисует вверху экрана, где живет строка состояния, и поэтому должен нести за нее ответственность. Поэтому реализация preferredStatusBarStyle
в ваших VCs в навигационном контроллере ничего не будет делать - они никогда не будут вызываться.
фокус в том, что UINavigationController
использует, чтобы решить, за чем возвращаться UIStatusBarStyleDefault
или UIStatusBarStyleLightContent
. Это основано на его UINavigationBar.barStyle
. Значение по умолчанию (UIBarStyleDefault
) результаты на темном переднем плане UIStatusBarStyleDefault
строка состояния. И UIBarStyleBlack
даст UIStatusBarStyleLightContent
строка состояния.
TL; DR:
если вы хотите UIStatusBarStyleLightContent
на UINavigationController
использование:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
поэтому я фактически добавил категорию В UINavigationController, но использовал методы:
-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;
и они возвращают текущий видимый UIViewController. Это позволяет текущему контроллеру видимого вида установить свой собственный предпочтительный стиль / видимость.
вот полный фрагмент кода для этого:
В Swift:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.topViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.topViewController
}
}
В Objective-C:
@interface UINavigationController (StatusBarStyle)
@end
@implementation UINavigationController (StatusBarStyle)
-(UIViewController *)childViewControllerForStatusBarStyle {
return self.topViewController;
}
-(UIViewController *)childViewControllerForStatusBarHidden {
return self.topViewController;
}
@end
и для хорошей меры, вот как это реализовано затем в UIViewController:
В Swift
override public func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
override func prefersStatusBarHidden() -> Bool {
return false
}
В Objective-C
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent; // your own style
}
- (BOOL)prefersStatusBarHidden {
return NO; // your own visibility code
}
наконец, убедитесь, что ваше приложение plist делает не установите для параметра" внешний вид строки состояния на основе контроллера вида " значение нет. Либо удалите эту строку, либо установите ее в YES (что, я считаю, теперь по умолчанию для iOS 7?)
для тех, кто все еще борется с этим, это простое расширение в swift должно решить проблему для вас.
extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
Тайсон ответ правильный для изменения цвета строки состояния на белый в UINavigationController
.
если кто-то хочет достичь того же результата, написав код в AppDelegate
затем используйте ниже код и напишите его внутри AppDelegate's
didFinishLaunchingWithOptions
метод.
и не забудьте установить UIViewControllerBasedStatusBarAppearance
to YES
в рамках .plist файл, иначе изменение не отразится.
код
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// status bar appearance code
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
return YES;
}
дополнение к ответу Hippo: если вы используете UINavigationController, то, вероятно, лучше добавить категорию:
// UINavigationController+StatusBarStyle.h:
@interface UINavigationController (StatusBarStyle)
@end
// UINavigationController+StatusBarStyle.m:
@implementation UINavigationController (StatusBarStyle)
- (UIStatusBarStyle)preferredStatusBarStyle
{
//also you may add any fancy condition-based code here
return UIStatusBarStyleLightContent;
}
@end
это решение, вероятно, лучше, чем переход к скорому устаревшему поведению.
@serenn это!--5-->ответ выше по-прежнему является отличным для случая UINavigationControllers. Однако для swift 3 функции childViewController были изменены на vars
. Так что UINavigationController
код расширения должны быть:
override open var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
override open var childViewControllerForStatusBarHidden: UIViewController? {
return topViewController
}
а затем в контроллере вида, который должен диктовать стиль строки состояния:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
Если ваш viewController находится под UINavigationController.
подкласс UINavigationController и добавить
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
в файле ViewController preferredStatusBarStyle
будет называться.
мое приложение использовало все три: UINavigationController
, UISplitViewController
, UITabBarController
, таким образом, все они, похоже, берут под контроль строку состояния и вызовут preferedStatusBarStyle
чтобы не звали их детей. Чтобы переопределить это поведение, вы можете создать расширение, как и в остальных ответах. Вот расширение для всех трех, в Swift 4. Хотелось бы, чтобы Apple была более ясна в таких вещах.
extension UINavigationController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
extension UISplitViewController {
open override var childViewControllerForStatusBarStyle: UIViewController? {
return self.childViewControllers.first
}
open override var childViewControllerForStatusBarHidden: UIViewController? {
return self.childViewControllers.first
}
}
UIStatusBarStyle в iOS 7
строка состояния в iOS 7 прозрачна,вид за ней отображается.
стиль строки состояния относится к появлению ее содержимого. В iOS 7 содержимое строки состояния либо темное (UIStatusBarStyleDefault
) или света (UIStatusBarStyleLightContent
). Оба!--3--> и UIStatusBarStyleBlackOpaque
устарели в iOS 7.0. Использовать UIStatusBarStyleLightContent
вместо.
как изменить UIStatusBarStyle
если ниже строки состояния находится панель навигации, стиль строки состояния будет скорректирован в соответствии со стилем панели навигации (UINavigationBar.barStyle
):
в частности, если стиль панели навигации UIBarStyleDefault, стиль строки состояния будет UIStatusBarStyleDefault
; Если стиль панели навигации UIBarStyleBlack
, стиль строки состояния будет UIStatusBarStyleLightContent
.
если под строкой состояния нет навигационной панели, стиль строки состояния может управляться и изменяться отдельным контроллером вида во время работы приложения.
-[UIViewController preferredStatusBarStyle]
- это новый метод добавлен в iOS 7. Его можно переопределить, чтобы вернуть предпочтительный стиль строки состояния:
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
если стиль строки состояния должен управляться контроллером дочернего представления вместо self, переопределите -[UIViewController childViewControllerForStatusBarStyle]
чтобы вернуть этот контроллер дочернего вида.
если вы предпочитаете отказаться от этого поведения и установить стиль строки состояния с помощью -[UIApplication statusBarStyle]
способ добавить UIViewControllerBasedStatusBarAppearance
ключ к приложению Info.plist
file и дайте ему значение NO.
Если кто-то использует навигационный контроллер и хочет, чтобы все их навигационные контроллеры имели черный стиль, вы можете написать расширение для UINavigationController, как это в Swift 3, и оно будет применяться ко всем навигационным контроллерам (вместо того, чтобы назначать его одному контроллеру за раз).
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barStyle = UIBarStyle.black
}
}
на UINavigationController, preferredStatusBarStyle
не вызывается, потому что его topViewController
предпочтительно self
. Итак, чтобы получить preferredStatusBarStyle
вызванный на UINavigationController, вам нужно изменить его childViewControllerForStatusBarStyle
.
сделать это для одного UINavigationController (моя рекомендация):
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
сделать это для всех UINavigationController (предупреждение: это влияет на UIDocumentPickerViewController, UIImagePickerController и т. д.):
extension UINavigationController {
public override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
public override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
Swift 3 iOS 10 Решение:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
вот мой метод решения этой проблемы.
определите протокол под названием AGViewControllerAppearance.
AGViewControllerAppearance.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
определить категорию по UIViewController под названием обновление.
UIViewController + Обновление.h
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
UIViewController + Обновление.м
#import "UIViewController+Upgrade.h"
#import <objc/runtime.h>
#import "AGViewControllerAppearance.h" // This is the appearance protocol
@implementation UIViewController (Upgrade)
+ (void)load
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wselector"
Method viewWillAppear = class_getInstanceMethod(self, @selector(viewWillAppear:));
#pragma clang diagnostic pop
Method upgradedViewWillAppear = class_getInstanceMethod(self, @selector(upgradedViewWillAppear:));
method_exchangeImplementations(viewWillAppear, upgradedViewWillAppear);
}
#pragma mark - Implementation
- (void)upgradedViewWillAppear:(BOOL)animated
{
//
// Call the original message (it may be a little confusing that we're
// calling the 'same' method, but we're actually calling the original one :) )
//
[self upgradedViewWillAppear:animated];
//
// Implementation
//
if ([self conformsToProtocol:@protocol(AGViewControllerAppearance)])
{
UIViewController <AGViewControllerAppearance> *viewControllerConformingToAppearance =
(UIViewController <AGViewControllerAppearance> *)self;
//
// Status bar
//
if ([viewControllerConformingToAppearance respondsToSelector:@selector(preferredStatusBarStyle)])
{
BOOL shouldAnimate = YES;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(animatesStatusBarVisibility)])
{
shouldAnimate = [viewControllerConformingToAppearance animatesStatusBarVisibility];
}
[[UIApplication sharedApplication] setStatusBarStyle:[viewControllerConformingToAppearance preferredStatusBarStyle]
animated:shouldAnimate];
}
if ([viewControllerConformingToAppearance respondsToSelector:@selector(showsStatusBar)])
{
UIStatusBarAnimation animation = UIStatusBarAnimationSlide;
if ([viewControllerConformingToAppearance respondsToSelector:@selector(prefferedStatusBarAnimation)])
{
animation = [viewControllerConformingToAppearance prefferedStatusBarAnimation];
}
[[UIApplication sharedApplication] setStatusBarHidden:(! [viewControllerConformingToAppearance showsStatusBar])
withAnimation:animation];
}
}
}
@end
теперь, пришло время сказать, что ты представление-контроллер реализует AGViewControllerAppearance протокол.
пример:
@interface XYSampleViewController () <AGViewControllerAppearance>
... the rest of the interface
@end
конечно, вы можете реализовать остальные методы (showsStatusBar, animatesStatusBarVisibility, prefferedStatusBarAnimation) из протокола а UIViewController + Обновление сделаете правильный настройка на основе предоставленных ими значений.
Если кто-то столкнется с этой проблемой с UISearchController. Просто создайте новый подкласс UISearchController, а затем добавьте код ниже в этот класс:
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
в Swift для любого вида UIViewController:
в своем AppDelegate
set:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window!.rootViewController = myRootController
return true
}
myRootController
может быть любого типа UIViewController
, например,UITabBarController
или UINavigationController
.
затем переопределите этот корневой контроллер вроде этого:
class RootController: UIViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
это изменит внешний вид строки состояния во всем приложении, потому что корневой контроллер несет полную ответственность за внешний вид строки состояния.
не забудьте установить свойство View controller-based status bar appearance
да в Info.plist
чтобы сделать эту работу (по умолчанию).
обратите внимание, что при использовании self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
решение
Не забудьте перейти к plist и установить "вид на основе контроллера строки состояния" да. Если его нет, он не будет работать.
в дополнение к ответу серенна, если вы представляете контроллер вида с modalPresentationStyle
(например,.overCurrentContext
), вы также должны вызвать это на вновь представленном контроллере представления:
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
не забудьте также переопределить preferredStatusBarStyle
В представленном контроллере вида.
большинство ответов не включают хорошую реализацию childViewControllerForStatusBarStyle
метод UINavigationController
. По моему опыту, вы должны обрабатывать такие случаи, когда прозрачный контроллер представления представлен над навигационным контроллером. В этих случаях вы должны передать управление своему модальному контроллеру (visibleViewController
), но не тогда, когда оно исчезает.
override var childViewControllerForStatusBarStyle: UIViewController? {
var childViewController = visibleViewController
if let controller = childViewController, controller.isBeingDismissed {
childViewController = topViewController
}
return childViewController?.childViewControllerForStatusBarStyle ?? childViewController
}
чтобы изменить цвет текста строки состояния в iOS 10 & iOS 11:
Ниже приведены случаи появления строки состояния на основе ViewController:
1) ViewController без NavigationController:
-(UIStatusBarStyle)preferredStatusBarStyle {
return UIStatusBarStyleLightContent;// Change according to your need
}
2) ViewController с NavigationController:
self.navigationController.navigationBar.barStyle = UIStatusBarStyleLightContent; // Change according to your need
ниже для изменения цвета текста строки состояния для всего приложения:
a) Add "View controller-based status bar appearance" in info.plist and set it to NO
b) Write following code in didFinishLaunchingWithOptions in AppDelegate as:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; // Change according to your need
return YES;
}
NavigationController или TabBarController-это те, которые должны предоставить стиль. Вот как я решил:https://stackoverflow.com/a/39072526/242769