UIStatusBarStyle PreferredStatusBarStyleがiOS 7で機能しない


110

Xcode 5 for iOS 7で構築された私のiPhoneアプリケーションで、私はに設定しUIViewControllerBasedStatusBarAppearance=YESましたinfo.plist、そして私のViewController中に次のコードがあります:

-(UIStatusBarStyle) preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

ただし、ステータスバーは黒い背景に対して黒いままです。

私は設定して、このアプリ全体で変更するにはその可能性を知っているUIViewControllerBasedStatusBarAppearance=NO中でinfo.plist、私は実際にこれを変更する必要があるviewControllerことでviewController、実行時に基礎。


こんにちは、私はあなたが問題に言及したのと同じ問題を抱えています。あなたは解決策を得ましたか?教えてください。
Noundla Sandeep、2015

回答:


281

ViewControllerがnavigationController内にある場合、navigationControllerがnavigationBar.barStylestatusBarStyleを決定することを発見しました。

navigationBarをに設定barStyleするUIBarStyleBlackTranslucentと、白いステータスバーテキスト(つまりUIStatusBarStyleLightContent)が表示され、UIBarStyleDefault黒いステータスバーテキスト(つまりUIStatusBarStyleDefault)が表示されます。

なお、これはあなたが完全にその経てnavigationBarの色を変更する場合にも適用されていることbarTintColor


これは私には理にかなっています...素晴らしい
ニック

14
これは、UINavigationController' preferredStatusBarStyleがホストするViewControllerを呼び出さず、代わりにそのnavigationBarStyleに基づいて戻るためだと思います。
mxcl 2013年

この場合、ビューはナビゲーションコントローラ内にありません。
Andrew Smith

モーダルビューを表示する場合にのみ、バーのスタイルがビューコントローラーに実装されたメソッドよりも優先されると考えるのは非常に直観的ではありません。
Matej

3
UIBarStyleBlackTranslucent は非推奨です。UIBarStyleBlack代わりに使用してください
Nguyen

87

OK、これがトリックです。「View controller-based status bar」キーを追加して、値をNoに設定する必要があります。

これは、このキーの意味とは逆ですが、値をNoに設定した場合でも、ステータスバーの外観を変更したり、ビューコントローラに表示するかどうかを変更したりできます。したがって、「はい」のように機能しますが、「いいえ」に設定します。

これで、ステータスバーを白または暗くすることができます。


6
私にとってこれは間違っていました。予想通り、キーを「はい」に設定する必要がありました。Xcode 5.1 iOS 7.1を使用しているため、変更された可能性があります。
joel.d 2014年

Xcode 5.1とiOS 7.1も使用していますが、うまくいきませんでした... STRANGE。
Arjun Mehta 14年

このキーはどこに追加すればよいですか?
Hadu

あなたの[AppNameは] -Info.plistファイルで
サレン印伝

1
「View controller-based status bar」キーが「YES」に設定されていて、Xcode6.0、iOS 8.0で
正常に機能する

77

以下のためのpreferredStatusBarStyle()仕事に内UINavigationControllerUITabBarController私は現在、目に見えるビューコントローラから優先ステータスバーのスタイルを取得する次のコードを追加します。

extension UITabBarController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return visibleViewController
    }
}

スウィフト3これらは、メソッドが、プロパティではありません。

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

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

スウィフト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
    }

}

6
これは断然最良の答えです(UINavigationControllerまたはUITabBarControllerを使用するアプリの場合
Kesava

1
これの使用法は何ですか?
AnBisw 2017年

@Annjawnこれらのメソッドは、UIKitによって使用されます。プロジェクトに追加する以外に何もする必要はありません。
ダニエルウッド

@DanielWoodええ、私はそれを理解し、以前のプロジェクトの1つでこれとまったく同じものを使用したことを完全に忘れましたが、少し異なります。
AnBisw 2017年

これは確かに最良の答えです
Musa almatri 2018

33

私はこれに少し遅れる可能性がありますが、他の誰かが動作し、検証されたアプリ全体のソリューションを探している場合に備えて。

@mxclは、これが発生している理由を説明するのに適切です。これを修正するには、UINavigationControllerのpreferredSatusBarStyle()メソッドをオーバーライドする拡張機能(またはobj-cのカテゴリ)を作成するだけです。これがSwiftの例です:

extension UINavigationController {
    public override func preferredStatusBarStyle() -> UIStatusBarStyle {
        if let rootViewController = self.viewControllers.first {
            return rootViewController.preferredStatusBarStyle()
        }
        return super.preferredStatusBarStyle()
    }
}

このコードは、最初のビューコントローラー(ルートビューコントローラー)を抽出して展開します(obj-cでnilでないことを確認してください)。アンラップが成功した(nilではない)場合は、rootViewControllers preferredStatusBarStyleを取得します。それ以外の場合は、デフォルトを返すだけです。

これがそれを必要とするかもしれない人を助けることを願っています


2
Swift 2.0では、条件ステートメントの「as?UIViewController」を削除する必要があります。
トーマスCalmon

見事な、私は "as"ステートメントを削除することに加えて1つの変更を行いました。私はそれを "最初"から "最後"に変更しました。これにより、スタックの一番上にあるユーザーがどのビューコントローラーを表示しても、制御できるようになります。ステータスバーの色。素晴らしい仕事、共有してくれてありがとう!
Unome 2015

1
ナビゲーションコントローラーにビューコントローラーがない場合、無限ループが発生します。 return self.preferredStatusBarStyle()これとまったく同じメソッドをコールバックします。
bearMountain 2016

1
私の場合、スタックの間にスタイルが変更される可能性があるため、rootViewControllerを使用する代わりにtopViewControllerを使用しました。
Ric Santos

2
@UnomeはvisibleViewControllerさらに良いでしょう
・クール

21

承認された回答の詳細を提供するには、アプリデリゲートのdidFinishLaunchingWithOptions:メソッドに次の行を追加します。

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;

次に、Info.plistに追加View controller-based status bar appearanceしてに設定しNOます。

アプリ全体で同じステータスバーの色が必要な場合は、ナビゲーションコントローラーからではなく、そのようにする必要があると思います。必ずしもUINavigationController、または別のUINavigationController場所の別のサブクラスなどに埋め込まれていない画面がある場合があります。

編集:コードを入力せずにそれを行うこともできます:https : //stackoverflow.com/a/18732865/855680


1
この方法はIOS 9.0から非推奨であることに注意してください
Mohamed Salah

10

viewDidLoadでこれを書くだけです

[self setNeedsStatusBarAppearanceUpdate];

それをするだけでうまくいきます

やってみてください

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

あなたの質問で私が見たもう一つのことは、あなたがこのような方法を書いたことです

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

しかし、それはこのようになるはずです

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
} 

これにより、preferredStatusBarStyleメソッドが呼び出されますが、ステータスバーは黒のままです。
Andrew Smith

私の更新された回答を参照してください..それが機能するかどうかをすぐに知らせてください
ユーザー1531343

私の元の質問では、ステータスバーのビューコントロールで表示する必要があると明確に述べています。
Andrew Smith

更新された質問を参考にしてコードを確認してください。
ユーザー1531343 2013年

1
[self setNeedsStatusBarAppearanceUpdate];そのような素晴らしい方法、ありがとう!
Supertecnoboff 2018

6

ここで私はそれを解決した方法です。通常、navigationControllerまたはtabBarControllerは、ステータスバーの外観(非表示、色など)を決定するものです。

そのため、ナビゲーションコントローラをサブクラス化し、preferredStatusBarStyleをオーバーライドしました。現在表示されているViewContorllerがStatusBarStyleHandlerを実装している場合、スタイルとして使用される値を要求します。そうでない場合は、デフォルト値を返します。

ステータスバーの外観の更新をトリガーする方法は、を呼び出しsetNeedsStatusBarAppearanceUpdatepreferredStatusBarStyle、メソッドが返す内容に従ってUIを更新し、トリガーします。

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

この投稿がなぜ、どのように問題を修正するかを説明できれば、この投稿は大幅に改善されます。

UINavigationControllerをサブクラス化する代わりに、UINavigationControllerの拡張を作成して、サブクラス化することなく同じ結果を得ることができます。
wilforeal

4

1)プロジェクト全体に1つの設定:

可能な場合UIViewControllerBasedStatusBarAppearanceは、info.plistからキーと値のペアを削除するか、削除NOせずに設定します。info.plistで使用できない場合は、何もしないでください。デフォルトはNOこのプロパティです。

以下のコードをAppDelegate.mに追加します。

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

2)異なるビューコントローラーの異なる設定:

UIViewControllerBasedStatusBarAppearanceキーと値のペアをinfo.plistに追加し、に設定しYESます。

View ControllerがNavigation Controllerに埋め込まれていない場合。MyViewControllerとしましょう。以下のコードをMyViewController.mファイルに追加するだけです。View ControllerがNavigation Controllerに埋め込まれている場合は、新しいCocoa Touch Classを作成し、それをUINavigationControllerのサブクラスにします。MyNCとしましょう。右側のペインで、ストーリーボードのナビゲーションコントローラービューを選択します。ユーティリティ-> Identity Inspector->カスタムクラス->クラス。「MyNC」と入力します。Storyboard Viewを「MyNC」Cocoa Touch Classにリンクした後、以下のコードをMyNC.mに追加します。

- (BOOL)prefersStatusBarHidden {
    return NO;
}

-(UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

iOS9のUIViewControllerBasedStatusBarAppearanceにはデフォルトで値YESが含まれているようです。適切に機能させるには、.plistに手動で追加してNOに設定する必要があったためです。
Mohd Asim

4

ここですべての答えがあっても、正確な解決策はまだ見つかりませんでしたが、ダニエルからの答えから始めました。私が終わったのは:

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

ナビゲーションコントローラー内(タブと同様、selectedViewControllerのみ)。そしてそれは尊重します:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return .lightContent
}

特に設定しない限り、各ビューコントローラで。私はsetNeedsStatusBarAppearanceUpdate()どこにも呼び出す必要はありません、それはあなたが各View Controllerに到着したときに更新されるだけです。


2
何時間もこれに苦労した後、私はほとんど同じソリューションで終わった。
Scott Jungwirth 2017

ある時点でこれは修正されたようで、各VCでpreferredStatusBarStyleを使用するだけでうまくいきます。
Andrew Plummer

4

iOS 13ソリューション

最高投票の回答には「レガシー」コードを使用します👎

barStyleプロパティの設定は(iOS 13以降)「レガシーカスタマイズ」と見なされます。アップルよると

iOS 13以降では、standardAppearance、compactAppearance、およびscrollEdgeAppearanceプロパティを使用してナビゲーションバーをカスタマイズします。これらのレガシーアクセサーを引き続き使用して、ナビゲーションバーの外観を直接カスタマイズできますが、さまざまなバー構成の外観を自分で更新する必要があります。

あなたの試みについて-あなたは正しい軌道に乗っていました!

UINavigationControllerUIViewController(whoを知っている)のサブクラスです!

したがって、ナビゲーションコントローラーに埋め込まれたビューコントローラーを提示する場合、埋め込まれたビューコントローラーは実際には提示されません。あなたはナビゲーションコントローラーを提示しています!UINavigationController、のサブクラスとしてUIViewControllerpreferredStatusBarStyleおよびを継承しchildForStatusBarStyle、必要に応じて設定できます。

次のいずれかの方法が機能するはずです。

  1. preferredStatusBarStyle内でオーバーライドUINavigationController

    • preferredStatusBarStyledoc)-ビューコントローラの優先ステータスバースタイル
    • サブクラスまたは拡張 UINavigationController

      class MyNavigationController: UINavigationController {
          override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }

      または

      extension UINavigationController {
          open override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }
  2. childForStatusBarStyle内でオーバーライドUINavigationController

    • childForStatusBarStyleドキュメント)-システムがステータスバーのスタイルを決定するために使用するビューコントローラーを必要とするときに呼び出されます
    • Appleのドキュメントによると、

      「コンテナビューコントローラがその子ビューコントローラの1つからステータスバースタイルを派生している場合は、[このプロパティをオーバーライドして]その子ビューコントローラを返します。nilを返すか、このメソッドをオーバーライドしない場合は、セルフのステータスバースタイルが使用されます。このメソッドからの戻り値が変更された場合は、setNeedsStatusBarAppearanceUpdate()メソッドを呼び出します。

    • つまり、ここでソリューション3を実装しない場合、システムは上記のソリューション2にフォールバックします。
    • サブクラスまたは拡張 UINavigationController

      class MyNavigationController: UINavigationController {
          override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }

      または

      extension UINavigationController {    
          open override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }
    • 上記の任意のビューコントローラを返すことができます。次のいずれかをお勧めします。

      • topViewController(of UINavigationController)(doc)-ナビゲーションスタックの最上部にあるビューコントローラー
      • visibleViewController(of UINavigationController)(doc)-ナビゲーションインターフェースで現在表示されているビューに関連付けられたビューコントローラー(ヒント:「ナビゲーションコントローラー自体の上にモーダルに表示されたビューコントローラー」を含めることができます)

注:サブクラス化する場合はUINavigationController、IBのIDインスペクターを使用して、そのクラスをナビゲーションコントローラーに適用してください。

PS私のコードはSwift 5.1構文を使用しています😎


1
非常に完全な答え、ありがとう!また、私がしばらく苦労した何か、iOS 13では.defaultスタイルはダークモードを考慮に入れており、ドキュメント化されていないため、以前のiOSバージョンもサポートしているif #available(iOS 13, *) { return .darkContent } else { return .default }場合は、ステータスバーの後ろの色とその色は「明るい」です。
バルカナイア

1
Xcode 11.4 / iOS 13.4でオーバーライド変数を実行する拡張メソッドが機能しないことに注意してください
Marc Etcheverry

Swiftでの目的Cクラスの拡張は、目的Cカテゴリを通じて実装されるためです。Objective Cカテゴリーによるメソッドのオーバーライドは推奨されておらず、機能しなくなる可能性があります。stackoverflow.com/a/38274660/2438634を
Marc Etcheverry

UINavigationControllerのオーバーライドは確実に機能しますが、Apple側のバグのように見えますが、デフォルトでは、そのtopViewControllerを返すchildForStatusBarStyleを実行しません。たとえば、UITabBarControllerはタブに対してこれを行います。私にとって、UINavigationControllerが、独自のUIを表示するのではなく、「実際の」Viewコントローラーをホストするための厳密なコンテナーコントローラーであり、これらのステータスバーのスタイルを「使い果たす」必要がある理由はありません。アップルのレーダーを作成します。
Igor Vasilev

1

splashScreen中にstatusBarを非表示にしたいが、スタイルを明るいコンテンツに変更したい場合(スプラッシュでstatusBarを非表示にするには、PlistのStatusBarInitiallyHiddenをNOにする必要があります)、これをappDelegateのdidFinishLaunchingWithOptionsメソッドに追加してlightContentに変更できます。

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

1

迅速な例

AppDelegate.swift

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

    return true
}

info.plist set inコントローラベースのステータスバーの外観を表示:いいえ


1

を使用している場合は、子ビューコントローラを参照するように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;
}

1

Swift 4.2

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

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

Xcode 11.4 / iOS 13.4でオーバーライド変数を実行する拡張メソッドが機能しないことに注意してください
Marc Etcheverry

@MarcEtcheverryだから、なぜあなたは答えを反対票を投じたのですか?奇妙に見えます。
ビャチェスラフ

Swiftでの目的Cクラスの拡張は、目的Cカテゴリを通じて実装されるためです。Objective Cカテゴリーによるメソッドのオーバーライドは推奨されておらず、機能しなくなる可能性があります。stackoverflow.com/a/38274660/2438634を
Marc Etcheverry

@MarcEtcheverry '非推奨'!= '決して使用しない!'。2018年7月の答えは正しかった。この回答でさえ最新ではありませんので、反対票を投じる理由にはなりません。未来が見えない
ヴィャチェスラフ

0

ステータスバーのスタイルを設定できます。これは、IOS 6以下のようなステータスバーに似ています。
このメソッドをビューコントローラーに貼り付けます

-(UIStatusBarStyle)preferredStatusBarStyle{
    return UIStatusBarStyleBlackOpaque;
}

ビューからこのメソッドを呼び出すと、このようにロードされました

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

あなたは意味するか[self setStatusBarNeedsUpdate]第二のブロックに?(または少なくとも何か他のもの)。
mxcl 2013年

0

私が直面した特定のケースに関するメモを追加したいだけです。アプリ内に別のUIWindowがあり、チャットの顔を常にアプリ全体に浮かび上がらせていました。これを行っても、上記の解決策はどれも機能しませんでした。その理由は本当にわかりません。私が気付いたことはすべて、新しいUIWindowの私のViewControllerがその理由だったということです。ステータスバーのスタイルを変更したい場合は、新しいUIWindowのビューコントローラーで行う必要があります。

このメモは、同様の構造を持つ他の人を助けるかもしれません!したがって、基本的には、上記のソリューションを新しいUIWindowのViewControllerに適用できます。

これも特定のケースです。

ありがとう


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.