-preferredStatusBarStyle
をオーバーライドするために このスレッド をたどりましたが、呼び出されません。有効にするために変更できるオプションはありますか? (私は自分のプロジェクトでXIBを使用しています。)
私は同じ問題を抱えていて、私は自分のアプリケーションウィンドウでルートView Controllerを設定していなかったのでそれが起こっていることを理解しました。
UIViewController
を実装したpreferredStatusBarStyle
は、画面上のビューの外観を制御するUITabBarController
で使用されていました。
このUITabBarController
を指すようにルートView Controllerを設定すると、ステータスバーの変更が正しく機能し始めました(そしてpreferredStatusBarStyle
メソッドが呼び出されました)。
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
... // other view controller loading/setup code
self.window.rootViewController = rootTabBarController;
[self.window makeKeyAndVisible];
return YES;
}
あるいは、setNeedsStatusBarAppearanceUpdate
を使用する代わりに、背景色に応じて、各View Controllerで次のメソッドのいずれかを適切に呼び出すことができます。
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
または
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
この方法を使用する場合は、plistファイルでUIViewControllerBasedStatusBarAppearance
をNO
に設定する必要もあります。
INavigationControllerを使っている人のために:
UINavigationController
は、その子View ControllerへのpreferredStatusBarStyle
の呼び出しを転送しません。その代わりにそれはそれ自身の状態を管理します - それは本来あるべきように、それはステータスバーが存在するスクリーンの一番上に描いているのでそれに責任があるべきです。そのため、navコントローラ内のあなたのVCにpreferredStatusBarStyle
を実装することは何もしないでしょう - それらは決して呼ばれないでしょう。
トリックは、UINavigationController
がUIStatusBarStyleDefault
またはUIStatusBarStyleLightContent
に何を返すかを決定するために使用するものです。これはUINavigationBar.barStyle
に基づいています。デフォルト(UIBarStyleDefault
)では、暗い前景のUIStatusBarStyleDefault
ステータスバーが表示されます。そしてUIBarStyleBlack
はUIStatusBarStyleLightContent
ステータスバーを与えます。
TL; DR:
UIStatusBarStyleLightContent
にUINavigationController
が必要な場合は、次のようにします。
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
だから私は実際にUINavigationControllerにカテゴリを追加しましたが、メソッドを使用しました:
-(UIViewController *)childViewControllerForStatusBarStyle;
-(UIViewController *)childViewControllerForStatusBarHidden;
そしてそれらに現在表示されているUIViewControllerを返させました。これにより、現在の可視のView Controllerが独自の好みのスタイル/可視性を設定できます。
これが完全なコードスニペットです。
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が動作することを確認してくださいNOT "View controller-based status bar appearance"をNOに設定してください。その行を削除するか、それをYESに設定してください(私は今iOS 7のデフォルトであると思いますか?)
まだこれに苦しんでいる人のために、Swiftのこの単純な拡張はあなたのために問題を解決するべきです。
extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
return self.topViewController
}
}
Tyson'sUINavigationController
でステータスバーの色を白に変更するのは正しい答えです。
誰かがAppDelegate
にコードを書くことによって同じ結果を達成したいならば、以下のコードを使って、そしてそれをAppDelegate's
didFinishLaunchingWithOptions
メソッドの中に書く。
そして、.plistファイルでUIViewControllerBasedStatusBarAppearance
をYES
に設定することを忘れないでください。そうしないと、変更は反映されません。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// status bar appearance code
[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];
return YES;
}
私のアプリはUINavigationController
、UISplitViewController
、UITabBarController
の3つすべてを使用していたので、これらはすべてステータスバーを制御しているように見え、preferedStatusBarStyle
が子に対して呼び出されないようにします。この振る舞いを無効にするために、残りの答えが述べたように拡張を作成することができます。これがSwift 4の3つすべての拡張です。Wish 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
}
}
編集:Swift 4.2 APIの変更に合わせて更新
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return self.topViewController
}
open override var childForStatusBarHidden: UIViewController? {
return self.topViewController
}
}
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
extension UISplitViewController {
open override var childForStatusBarStyle: UIViewController? {
return self.children.first
}
open override var childForStatusBarHidden: UIViewController? {
return self.children.first
}
}
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
その解決策は、近いうちに廃止予定の動作に切り替えるよりもおそらく優れています。
UINavigationControllerでは、preferredStatusBarStyle
はtopViewController
よりも優先されるため、self
は呼び出されません。そのため、UINavigationControllerでpreferredStatusBarStyle
を呼び出すには、そのchildViewControllerForStatusBarStyle
を変更する必要があります。
1つのUINavigationControllerに対してこれを行うには(私の推奨):
class MyRootNavigationController: UINavigationController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
すべてのUINavigationControllerに対してこれを実行するには(警告:UIDocumentPickerViewController、UIImagePickerControllerなどに影響します)。
extension UINavigationController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
open override var childViewControllerForStatusBarStyle: UIViewController? {
return nil
}
}
@ serennの answer は、UINavigationControllersの場合にはまだ優れたものです。しかし、Swift 3では、childViewController関数はvars
に変更されました。そのため、UINavigationController
拡張コードは次のようになります。
override open var childViewControllerForStatusBarStyle: UIViewController? {
return topViewController
}
override open var childViewControllerForStatusBarHidden: UIViewController? {
return topViewController
}
そして、ステータスバーのスタイルを指示するべきView Controllerで:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
あなたのviewControllerがUINavigationControllerの下にある場合。
サブクラスUINavigationControllerと追加
override var preferredStatusBarStyle: UIStatusBarStyle {
return topViewController?.preferredStatusBarStyle ?? .default
}
ViewControllerのpreferredStatusBarStyle
が呼び出されます。
Serennの回答に加えて、modalPresentationStyle
name__(例えば.overCurrentContext
)を付けてView Controllerを表示している場合は、新しく表示されたView Controllerでこれを呼び出す必要があります。
presentedViewController.modalPresentationCapturesStatusBarAppearance = true
表示されているView ControllerのpreferredStatusBarStyle
name__もオーバーライドすることを忘れないでください。
選択した回答 で述べたように、根本的な原因は、ウィンドウのルートビューコントローラーオブジェクトをチェックすることです。
childForStatusBarStyle
を見つけるためにUINavigationController拡張機能に同じチェックを追加しました次の拡張機能を使用して、上記のすべてのシナリオを処理します-
extension UITabBarController {
open override var childForStatusBarStyle: UIViewController? {
return selectedViewController?.childForStatusBarStyle ?? selectedViewController
}
}
extension UINavigationController {
open override var childForStatusBarStyle: UIViewController? {
return topViewController?.childForStatusBarStyle ?? topViewController
}
}
extension AppRootViewController {
open override var preferredStatusBarStyle: UIStatusBarStyle {
return children.first { $0.childForStatusBarStyle != nil }?.childForStatusBarStyle?.preferredStatusBarStyle ?? .default
}
}
info.plist
にUIViewControllerBasedStatusBarAppearance
キーは必要ありません。デフォルトではtrueです新しいフローをモーダルで提示する場合、既存のステータスバースタイルのフローから切り離されます。したがって、NewFlowUIViewController
を表示してから、新しいNavigationまたはtabBarコントローラーをNewFlowUIViewController
に追加し、さらにNewFlowUIViewController
の拡張機能を追加して、さらにビューコントローラーのステータスバースタイルを管理するとします。
モーダル表示中にfullScreen
以外のmodalPresentationStyleを設定する場合は、modalPresentationCapturesStatusBarAppearance
をtrueに設定して、表示されるView Controllerがステータスバーの外観コントロールを受け取ります。
iOS 7のUIStatusBarStyle
IOS 7のステータスバーは透明で、その背後のビューは透けて見えます。
ステータスバーのスタイルは、そのコンテンツの外観を表します。 iOS 7では、ステータスバーの内容は濃い色(UIStatusBarStyleDefault
)または薄い色(UIStatusBarStyleLightContent
)です。 UIStatusBarStyleBlackTranslucent
とUIStatusBarStyleBlackOpaque
はどちらもiOS 7.0では非推奨です。代わりにUIStatusBarStyleLightContent
を使用してください。
UIStatusBarStyle
を変更する方法
ステータスバーの下にナビゲーションバーがある場合、ステータスバーのスタイルはナビゲーションバーのスタイル(UINavigationBar.barStyle
)と一致するように調整されます。
具体的には、ナビゲーションバーのスタイルがUIBarStyleDefaultの場合、ステータスバーのスタイルはUIStatusBarStyleDefault
になります。ナビゲーションバーのスタイルがUIBarStyleBlack
の場合、ステータスバーのスタイルはUIStatusBarStyleLightContent
になります。
ステータスバーの下にナビゲーションバーがない場合、ステータスバーのスタイルは、アプリケーションの実行中に個々のView Controllerによって制御および変更できます。
-[UIViewController preferredStatusBarStyle]
はiOS 7で追加された新しいメソッドです。優先ステータスバースタイルを返すようにオーバーライドすることができます。
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
ステータスバーのスタイルをselfではなく子のView Controllerで制御する必要がある場合は、-[UIViewController childViewControllerForStatusBarStyle]
をオーバーライドしてその子のView Controllerを返します。
この動作を無効にして-[UIApplication statusBarStyle]
メソッドを使用してステータスバーのスタイルを設定する場合は、UIViewControllerBasedStatusBarAppearance
キーをアプリのInfo.plist
ファイルに追加して値NOを指定します。
誰かがNavigation Controllerを使用していて、すべてのNavigation Controllerを黒スタイルにしたい場合は、Swift 3でこのようにUINavigationControllerに拡張機能を記述することができます。時間)。
extension UINavigationController {
override open func viewDidLoad() {
super.viewDidLoad()
self.navigationBar.barStyle = UIBarStyle.black
}
}
Swift 3 iOS 10ソリューション:
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
誰かがUISearchControllerでこの問題に遭遇した場合。 UISearchControllerの新しいサブクラスを作成し、そのクラスに以下のコードを追加してください。
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
あらゆる種類のUIViewControllerのSwiftでは
AppDelegate
セットで:
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
をYESに設定することを忘れないでください(これがデフォルトです)。
ほとんどの回答には、childViewControllerForStatusBarStyle
に対するUINavigationController
メソッドの適切な実装は含まれていません。私の経験によれば、透明なView ControllerがNavigation Controllerの上に表示される場合などに対処する必要があります。このような場合は、モーダルコントローラー(visibleViewController
)に制御を渡す必要がありますが、表示されなくなったときはそうしないでください。
override var childViewControllerForStatusBarStyle: UIViewController? {
var childViewController = visibleViewController
if let controller = childViewController, controller.isBeingDismissed {
childViewController = topViewController
}
return childViewController?.childViewControllerForStatusBarStyle ?? childViewController
}
これを解決するための私の方法です。
AGViewControllerAppearanceというプロトコルを定義します。
AGViewControllerAppearance.h
#import <Foundation/Foundation.h>
@protocol AGViewControllerAppearance <NSObject>
@optional
- (BOOL)showsStatusBar;
- (BOOL)animatesStatusBarVisibility;
- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIStatusBarAnimation)prefferedStatusBarAnimation;
@end
IViewControllerと呼ばれるpgradeでカテゴリを定義します。
IViewController + Upgrade.h
#import <UIKit/UIKit.h>
@interface UIViewController (Upgrade)
//
// Replacements
//
- (void)upgradedViewWillAppear:(BOOL)animated;
@end
IViewController + 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
さて、あなたはView ControllerがAGViewControllerAppearanceプロトコルを実装していると言う時が来ました。
例:
@interface XYSampleViewController () <AGViewControllerAppearance>
... the rest of the interface
@end
もちろん、残りのメソッド(showsStatusBar、animatesStatusBarVisibility、prefferedStatusBarAnimation)をプロトコルから実装することも、IViewController + Upgrade]はそれらが提供する値に基づいて適切なカスタマイズを行います。
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
ソリューションを使用するときは注意してください
必ずplistに行き、 "View controller-based status bar appearance"をYESに設定してください。いいえの場合それは動作しません。