preferredStatusBarStyle не называется
Я следил за этой нитью, чтобы переопределить -preferredStatusBarStyle
, но это не называется.
Есть ли какие-либо варианты, которые я могу изменить, чтобы включить его? (Я использую XIBs в своем проекте.)
21 ответ:
возможные причины
у меня была та же проблема, и я понял, что это происходит, потому что я не устанавливал контроллер корневого представления в своем окне приложения.
The
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
доNO
в файл plist, если вы используете этот метод.
для тех, кто использует UINavigationController:
The
UINavigationController
не наpreferredStatusBarStyle
вызывает дочерние контроллеры представления. Вместо этого он управляет своим собственным состоянием - как и должно быть, он рисует в верхней части экрана, где живет строка состояния, и поэтому должен отвечать за нее. Поэтому реализацияpreferredStatusBarStyle
в вашем VCs в навигационном контроллере ничего не будет делать-они никогда не будут вызваны.фокус в том, что
UINavigationController
использует для принятия решения за что возвращатьсяUIStatusBarStyleDefault
илиUIStatusBarStyleLightContent
. Он основывает это на своемUINavigationBar.barStyle
. Значение по умолчанию (UIBarStyleDefault
) результаты на темном переднем планеUIStatusBarStyleDefault
строка состояния. ИUIBarStyleBlack
даст aUIStatusBarStyleLightContent
строка состояния.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 } }
В Объективе-C:
@interface UINavigationController (StatusBarStyle) @end @implementation UINavigationController (StatusBarStyle) -(UIViewController *)childViewControllerForStatusBarStyle { return self.topViewController; } -(UIViewController *)childViewControllerForStatusBarHidden { return self.topViewController; } @end
и для хорошей меры, вот как это реализовано затем в UIViewController:
Быстро
override public func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func prefersStatusBarHidden() -> Bool { return false }
В Объективе-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
доYES
в рамках .plist файл, иначе изменение не будет отражать.код
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // status bar appearance code [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]; return YES; }
дополнение к ответу Гиппо: если вы используете 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
). ОбаUIStatusBarStyleBlackTranslucent
и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
файл и дать ему значение нет.
Если кто-то использует навигационный контроллер и хочет, чтобы все их навигационные контроллеры имели черный стиль, вы можете написать расширение для 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 + Upgrade будет делать правильный настройка на основе значений, предоставленных ими.
Если кто-то столкнется с этой проблемой с 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 и установите "внешний вид строки состояния на основе контроллера вида" в YES. Если его нет, он не будет работать.
в дополнение к ответу серенна, если вы представляете контроллер вида с
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