iOS 7でStatusBarの扱いも変わりました。デフォルトではアプリケーション単位ではなくViewController単位、つまり画面単位で扱うようになりました。これにより従来の方法だとStatusBarのスタイル(UIStatusBarStyle)が変わらなかったり、非表示にならない場合があります。

StatusBarの外観はViewController単位で行う

iOS 7のデフォルトの挙動はこれです。この場合、UIApplication#setStatusBarStyle,setStatusBarHiddenを使っても、文字色は変更できず、非表示になりません。以下のようにStatusBarの外観を変更します。

StatusBarの文字色を白色にする

デフォルトのStatusBarの文字色は黒ですが、Viewの背景色が黒などの場合、白にしたいはずです。その場合、ViewControllerのsubclassで以下のメソッドを実装します。

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

ただし、UINavigationControllerやUITabBarControllerの場合、その中身のViewControllerで上記のようにしても変化はありません。以下のようにUINavigationController、UITabBarControllerのカテゴリメソッドとして実装する必要があります。

@implementation UINavigationController (MyAppStatusBarStyle)

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

@end

もしくはUINavigationController、UITabBarControllerのsubclassで実装してもよいです。

※ 以前はドキュメントにUINavigationController、UITabBarControllerのsubclassを作らないように書かれていましたが、iOS 6からはsubclassにしても良いとされています。

単にViewControllerのみで表示する場合、そのViewControllerごとにpreferredStatusBarStyleを実装するのは面倒なので、基本クラスを作ってそこで実装し、あとはそのクラスを継承するようにすると楽です。ただ実際には、ほとんどのViewControllerはNavigationControllerの中身として表示されると思うので、上記のようにカテゴリメソッドを実装すれば、ほとんどの場合をカバーできるでしょう。

StatusBarを非表示にする

これもViewController単位で行います。

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

ちなみにこれはNavigationControllerやTabBarControllerの中身のViewControllerであっても機能します。

StatusBarの表示・非表示を動的に変更する、アニメーションする

この場合、StatusBarの表示・非表示の状態をViewControllerのプロパティなどで持っておくとよいでしょう。

@interface MyViewController ()

@property (nonatomic) BOOL currentStatusBarHidden;

@end

そして、この値をprefersStatusBarHiddenで返すようにします。

- (BOOL)prefersStatusBarHidden
{
    return _currentStatusBarHidden;
}

値を変更した時にsetNeedsStatusBarAppearanceUpdateを呼ぶようにします。またアニメーションしたいときは、このメソッドをUIView#animationWithDuration:animations:のブロック関数で呼びます。

- (void)setCurrentStatusBarHidden:(BOOL)statusBarHidden animated:(BOOL)animated
{
    _currentStatusBarHidden = statusBarHidden;
    if (animated) {
        [UIView animateWithDuration:0.3 animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
        }];
    } else {
        [self setNeedsStatusBarAppearanceUpdate];
    }
}

アニメーションはフェード(デフォルト)とスライドの2パターンを指定できます。以下のメソッドを実装して変更できます。

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    // UIStatusBarAnimationFade(Default)
    return UIStatusBarAnimationSlide;
}

StatusBarの外観を従来のアプリケーション単位で行う

従来のようにUIApplication#setStatusBarStyle, setStatusBarHiddenを使いたい場合は、アプリケーションのplistファイルで以下の設定を加える必要があります。

001

View controller-based statusBar appearanceをNOに設定することで、ViewController単位でStatusBarの外観を管理するのをやめることになり、従来の方法になります。デフォルトは項目自体存在せず、その場合はYESと同じ扱いになります。

StatusBarの文字色を白にする

以下をAppDelegate#application:didFinishLaunchingWithOptionsで行います。

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

StatusBarを非表示にする

[[UIApplication sharedApplication] setStatusBarHidden:YES];

ViewController単位、Application単位どちらにすべきか?

個人的には以下の理由からViewController単位が良いと思います。

  • StatusBarの外観や非表示は画面ごとに管理するほうが自然
  • アプリケーション単位で管理すると画面の遷移で表示・非表示のタイミングを間違ってバグに繋がりやすい
  • iOS 7のデフォルトの挙動である。それを変更して他に影響が広がらない方がいい

ViewController単位で行うことのデメリットは、先に述べたように文字色を白にしたい場合、ViewControllerごとにpreferredStatusBarStyleを実装する必要があることです。通常、ほとんどの画面ではStatusBarの文字色は同じにしたいので面倒に思うかもしれません。ただ、これも先に述べたようにほとんどの場合はNavigationControllerのカテゴリメソッドの実装と、アプリケーション共有の基本ViewControllerクラスでの実装で解決できると思います。

以下はViewController単位(ViewController-based)とアプリケーション単位でのStatusBarの文字色変更、非表示のサンプルです。

https://github.com/stack3/iOS7StatusBarSamples