ios ios7 uikit uistatusbar

ios - preferredStatusBarStyle no se llama



ios7 uikit (21)

Posible causa raíz

Tuve el mismo problema y descubrí que estaba sucediendo porque no estaba configurando el controlador de vista raíz en la ventana de mi aplicación.

El UIViewController en el que había implementado UIViewController preferredStatusBarStyle se usó en un UITabBarController , que controlaba el aspecto de las vistas en la pantalla.

Cuando configuro el controlador de vista raíz para que apunte a este UITabBarController , los cambios de la barra de estado comenzaron a funcionar correctamente, como se esperaba (y se llamó al método preferredStatusBarStyle ).

(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... // other view controller loading/setup code self.window.rootViewController = rootTabBarController; [self.window makeKeyAndVisible]; return YES; }

Método alternativo (obsoleto en iOS 9)

Alternativamente, puede llamar a uno de los siguientes métodos, según corresponda, en cada uno de sus controladores de vista, dependiendo de su color de fondo, en lugar de tener que usar setNeedsStatusBarAppearanceUpdate :

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

o

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];

Tenga en cuenta que también deberá establecer UIViewControllerBasedStatusBarAppearance en NO en el archivo plist si utiliza este método.

Seguí este hilo para anular -preferredStatusBarStyle , pero no se llama. ¿Hay alguna opción que pueda cambiar para habilitarlo? (Estoy usando XIBs en mi proyecto.)


Además de la respuesta de serenn, si está presentando un controlador de vista con un estilo modalPresentationStyle (por ejemplo .overCurrentContext ), también debe llamar a este controlador de vista recién presentado:

presentedViewController.modalPresentationCapturesStatusBarAppearance = true

No olvide anular también el preferredStatusBarStyle en el controlador de vista presentado.


Aquí está mi método para resolver esto.

Defina un protocolo llamado AGViewControllerAppearance .

AGViewControllerAppearance.h

#import <Foundation/Foundation.h> @protocol AGViewControllerAppearance <NSObject> @optional - (BOOL)showsStatusBar; - (BOOL)animatesStatusBarVisibility; - (UIStatusBarStyle)preferredStatusBarStyle; - (UIStatusBarAnimation)prefferedStatusBarAnimation; @end

Defina una categoría en UIViewController llamada Actualización .

UIViewController + Upgrade.h

#import <UIKit/UIKit.h> @interface UIViewController (Upgrade) // // Replacements // - (void)upgradedViewWillAppear:(BOOL)animated; @end

UIViewController + Upgrade.m

#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

Ahora, es el momento de decir que su controlador de vista está implementando el protocolo AGViewControllerAppearance .

Ejemplo:

@interface XYSampleViewController () <AGViewControllerAppearance> ... the rest of the interface @end

Por supuesto, puede implementar el resto de los métodos ( showsStatusBar , animatesStatusBarVisibility , prefferedStatusBarAnimation ) desde el protocolo y UIViewController + Upgrade hará la personalización adecuada en función de los valores proporcionados por ellos.


Así que en realidad agregué una categoría a UINavigationController pero usé los métodos:

-(UIViewController *)childViewControllerForStatusBarStyle; -(UIViewController *)childViewControllerForStatusBarHidden;

y tenía que devolver el actual UIViewController visible. Eso permite que el controlador de vista visible actual establezca su propio estilo / visibilidad preferidos.

Aquí hay un fragmento de código completo para ello:

En Swift:

extension UINavigationController { public override func childViewControllerForStatusBarHidden() -> UIViewController? { return self.topViewController } public override func childViewControllerForStatusBarStyle() -> UIViewController? { return self.topViewController } }

En Objective-C:

@interface UINavigationController (StatusBarStyle) @end @implementation UINavigationController (StatusBarStyle) -(UIViewController *)childViewControllerForStatusBarStyle { return self.topViewController; } -(UIViewController *)childViewControllerForStatusBarHidden { return self.topViewController; } @end

Y por si acaso, aquí está cómo se implementa en un UIViewController:

En Swift

override public func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } override func prefersStatusBarHidden() -> Bool { return false }

En Objective-C

-(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; // your own style } - (BOOL)prefersStatusBarHidden { return NO; // your own visibility code }

Finalmente, asegúrese de que la lista de su aplicación NO tenga la opción "Ver apariencia de la barra de estado basada en el controlador" configurada en NO. Borre esa línea o configúrela en SÍ (¿cuál creo que es la predeterminada ahora para iOS 7?)


En un UINavigationController, preferredStatusBarStyle no se llama porque su topViewController es preferido a self . Por lo tanto, para llamar a preferredStatusBarStyle en un UINavigationController, debe cambiar su childViewControllerForStatusBarStyle .

Para hacerlo por un UINavigationController (mi recomendación):

class MyRootNavigationController: UINavigationController { override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } override var childViewControllerForStatusBarStyle: UIViewController? { return nil } }

Para hacerlo para todos los UINavigationController (advertencia: afecta a UIDocumentPickerViewController, UIImagePickerController, etc.):

extension UINavigationController { open override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } open override var childViewControllerForStatusBarStyle: UIViewController? { return nil } }


La answer @ serenn arriba sigue siendo excelente para el caso de UINavigationControllers. Sin embargo, para swift 3, las funciones childViewController se han cambiado a vars . Así que el código de extensión UINavigationController debería ser:

override open var childViewControllerForStatusBarStyle: UIViewController? { return topViewController } override open var childViewControllerForStatusBarHidden: UIViewController? { return topViewController }

Y luego en el controlador de vista que debe dictar el estilo de la barra de estado:

override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }


La mayoría de las respuestas no incluyen una buena implementación del método UINavigationController para UINavigationController . Según mi experiencia, debe manejar casos como cuando el controlador de vista transparente se presenta sobre el controlador de navegación. En estos casos, debe pasar el control a su controlador modal ( visibleViewController ), pero no cuando está desapareciendo.

override var childViewControllerForStatusBarStyle: UIViewController? { var childViewController = visibleViewController if let controller = childViewController, controller.isBeingDismissed { childViewController = topViewController } return childViewController?.childViewControllerForStatusBarStyle ?? childViewController }


Mi aplicación usó los tres: UINavigationController , UISplitViewController , UITabBarController , por lo que parece que todos toman el control de la barra de estado y harán que no se llame a UITabBarController para sus hijos. Para anular este comportamiento, puede crear una extensión como el resto de las respuestas han mencionado. Aquí hay una extensión para los tres, en Swift 4. Ojalá Apple tuviera más claridad sobre este tipo de cosas.

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


NavigationController o TabBarController son los que necesitan proporcionar el estilo. Aquí es cómo resolví: https://.com/a/39072526/242769


Para cualquier persona que todavía esté luchando con esto, esta simple extensión en swift debería solucionar el problema por usted.

extension UINavigationController { override open var childViewControllerForStatusBarStyle: UIViewController? { return self.topViewController } }


Si alguien está usando un controlador de navegación y desea que todos sus controladores de navegación tengan el estilo negro, puede escribir una extensión para UINavigationController como esta en Swift 3 y se aplicará a todos los controladores de navegación (en lugar de asignarlo a un controlador a una hora).

extension UINavigationController { override open func viewDidLoad() { super.viewDidLoad() self.navigationBar.barStyle = UIBarStyle.black } }


Si alguien se encuentra con este problema con UISearchController. Simplemente crea una nueva subclase de UISearchController y luego agrega el código a continuación en esa clase:

override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent }


Si su viewController está bajo UINavigationController.

Subclase UINavigationController y add

override var preferredStatusBarStyle: UIStatusBarStyle { return topViewController?.preferredStatusBarStyle ?? .default }

Se llamará el estado de barra preferredStatusBarStyle de ViewController.


Swift 3 iOS 10 Solution:

override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }


Tenga en cuenta que al usar self.navigationController.navigationBar.barStyle = UIBarStyleBlack; solución

asegúrese de ir a su lista y configurar "Ver el aspecto de la barra de estado basada en el controlador" en SÍ. Si es NO no funcionará.


Una adición a la respuesta de Hippo: si está usando un controlador de control de UIN, entonces probablemente sea mejor agregar una categoría:

// 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

Esa solución es probablemente mejor que cambiar a un comportamiento pronto obsoleto.


En Swift para cualquier tipo de UIViewController:

En su conjunto de AppDelegate :

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { window!.rootViewController = myRootController return true }

myRootController puede ser cualquier tipo de UIViewController , por ejemplo, UITabBarController o UINavigationController .

Luego, anula este controlador raíz de esta manera:

class RootController: UIViewController { override func preferredStatusBarStyle() -> UIStatusBarStyle { return .LightContent } }

Esto cambiará la apariencia de la barra de estado en toda la aplicación, ya que el controlador raíz es el único responsable de la apariencia de la barra de estado.

Recuerde configurar la View controller-based status bar appearance en SÍ en su Info.plist para que esto funcione (que es el valor predeterminado).


La respuesta de Tyson es correcta para cambiar el color de la barra de estado a blanco en UINavigationController .

Si alguien quiere lograr el mismo resultado escribiendo el código en AppDelegate , use el siguiente código y escríbalo dentro AppDelegate''s método didFinishLaunchingWithOptions AppDelegate''s .

Y no olvide configurar UIViewControllerBasedStatusBarAppearance en YES en el archivo .plist, de lo contrario, el cambio no se reflejará.

Código

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // status bar appearance code [[UINavigationBar appearance] setBarStyle:UIBarStyleBlack]; return YES; }


Para cambiar el color del texto de la barra de estado en iOS 10 y iOS 11:

Los siguientes son los casos para la apariencia de la barra de estado basada en ViewController:

1) ViewController sin un NavigationController:

-(UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent;// Change according to your need }

2) ViewController con un NavigationController:

self.navigationController.navigationBar.barStyle = UIStatusBarStyleLightContent; // Change according to your need

Lo siguiente es para cambiar el color del texto de la barra de estado para toda la aplicación:

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; }


Para cualquier persona que use un controlador UINavigation:

El UINavigationController no reenvía preferredStatusBarStyle llamadas preferredStatusBarStyle a sus controladores de vista secundarios. En su lugar, administra su propio estado; como debe ser, se está dibujando en la parte superior de la pantalla donde vive la barra de estado y, por lo tanto, debe ser responsable de ello. Por lo tanto, la implementación de preferredStatusBarStyle en sus VC dentro de un controlador de navegación no hará nada, nunca se llamará.

El truco es lo que UINavigationController utiliza para decidir qué devolver para UIStatusBarStyleDefault o UIStatusBarStyleLightContent . Basa esto en su UINavigationBar.barStyle . El valor predeterminado ( UIBarStyleDefault ) da como resultado la barra de estado oscura oscura de UIStatusBarStyleDefault . Y UIBarStyleBlack dará una UIStatusBarStyleLightContent estado UIStatusBarStyleLightContent .

TL; DR:

Si desea que UIStatusBarStyleLightContent en un UINavigationController use:

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;


UIStatusBarStyle en iOS 7

La barra de estado en iOS 7 es transparente, la vista detrás de ella se muestra a través.

El estilo de la barra de estado se refiere a las apariencias de su contenido. En iOS 7, el contenido de la barra de estado es oscuro ( UIStatusBarStyleDefault ) o claro ( UIStatusBarStyleLightContent ). Tanto UIStatusBarStyleBlackTranslucent como UIStatusBarStyleBlackOpaque están en desuso en iOS 7.0. Utilice en UIStatusBarStyleLightContent lugar UIStatusBarStyleLightContent .

Cómo cambiar UIStatusBarStyle

Si debajo de la barra de estado hay una barra de navegación, el estilo de la barra de estado se ajustará para que coincida con el estilo de la barra de navegación ( UINavigationBar.barStyle ):

Específicamente, si el estilo de la barra de navegación es UIBarStyleDefault, el estilo de la barra de estado será UIStatusBarStyleDefault ; Si el estilo de la barra de navegación es UIBarStyleBlack , el estilo de la barra de estado será UIStatusBarStyleLightContent .

Si no hay una barra de navegación debajo de la barra de estado, un controlador de vista individual puede controlar y cambiar el estilo de la barra de estado mientras se ejecuta la aplicación.

- [UIViewController preferredStatusBarStyle] es un nuevo método agregado en iOS 7. Se puede anular para devolver el estilo de barra de estado preferido:

- (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; }

Si el estilo de la barra de estado debe ser controlado por un controlador de vista secundario en lugar de uno mismo, -[UIViewController childViewControllerForStatusBarStyle] para devolver ese controlador de vista secundario.

Si prefiere excluirse de este comportamiento y establecer el estilo de la barra de estado utilizando el método -[UIApplication statusBarStyle] , agregue la clave Info.plist archivo Info.plist la aplicación y Info.plist el valor NO.