ObjecTips

基本Objective-Cで iOS とか OS X とか

UIActivityViewController からメールが呼び出された時の statusBarStyle の調整

UIActivityViewController からメールが呼びだされた時に statusBarStyle が常に UIStatusBarStyleDefault で黒文字になってしまう。通常は問題無いがアプリのデザインでナビゲーションバーやボタン類に色を付けている場合、ステータスバーの文字色とマッチしない事がある。

f:id:Koze:20171119095954p:plain

Stack Overflow で検索してみると

  • Info.plist で UIViewControllerBasedStatusBarAppearanceNO にして UIStatusBarStyleUIStatusBarStyleLightContent に設定する
  • ViewController の表示や非表示の良きタイミングで以下のコードで設定
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];

という話が出てくる。

ところが iOS 11 で試してみたところ Info.plist での設定がうまく効かず(以前はこれでいけた様な?)またコードでの設定は iOS 9 で deprecated になっており今後完全に remove になる可能性もあるので他の方法も探してみる。

メールが起動された時の画面を Debug View Hierarchy で確認してみると MFMailComposeViewController と他2つの Private な MFMailComposeInternalViewController MFMailComposeRemoteViewController クラスが使われている事が分かった。

f:id:Koze:20171119094325p:plain

MFMailComposeViewController は公開クラスなので、カテゴリで既存メソッドをオーバーライドすれば挙動を変える事が出来る(ただしデフォルト挙動の書き換えはリスクを鑑みて変更は最小限にしておいた方が良い)。
実装は以下

Change the status bar to white when MFMailComposeV ...

UIViewControllerBasedStatusBarAppearance = YES の時

以下の2つのメソッドが呼ばれる。

- (UIStatusBarStyle)preferredStatusBarStyle;
- (UIViewController *)childViewControllerForStatusBarStyle;

MFMailComposeViewController のモーダルアニメーションと同時にステータスバーのスタイルが変更される。
このケースでは viewDidAppear: はオーバーライドしなくてもOK。

UIViewControllerBasedStatusBarAppearance = NO の時

以下のメソッドが呼ばれる。

- (void)viewDidAppear:(BOOL)animated;

先の2つのメソッドは呼ばれない。
MFMailComposeViewController のモーダルアニメーションの完了のタイミングの viewDidAppear: でステータスバーのスタイルが変更される。
このケースでは viewDidAppear: のみをオーバーライドすればOK。 *1

これで以下の様にメール画面でのステータスバーのスタイルを UIStatusBarStyleLightContent に変更する事が出来る。

f:id:Koze:20171119100025p:plain

*1:[super viewDidAppear:animated] は MFMailComposeViewController ではなくてその親クラスの UIViewController の実装を呼び出している。なくても良い。