Objective-Cのアプリをダークモード対応した
Objective-Cで書いている古いアプリを毎月メンテしています。
Xcode 11でビルドしたところ中途半端にダークモード対応となったため、急遽iOS13のダークモード対応にしました。
この記事は有料ですが期間限定で全部読めます。
♡クリックやシェアなどでご支援いただけるとありがたいです。
WWDCビデオで確認
ダークモード対応の全体像はWWDC2019のセッション214『Implementing Dark Mode on iOS』(英語)のビデオで確認しました。
現在日本語字幕を表示できます。
私はWWDCのすべてのスライドPDFをローカルにダウンロードしています。
メソッド名などで検索できて便利なのです。
このビデオだけで私の場合、ダークモード対応に必要な作業の情報はすべてありました。
ただしメソッド名やプロパティ名はすべてSwift言語なのでObjective-Cの場合は注意が必要です。
だいたい想像がつきますが、不明な場合はドキュメントをSwiftのメソッド名で検索し言語指定をObjective-Cに切り替えて確認しました。
背景色と文字色
まずは背景色と文字色の指定をダークモード対応にしました。
次のような関数をいくつか作りました。
UIColor *systemBackgroundColor(void) {
if (@available(iOS 13.0, *)) {
return UIColor.systemBackgroundColor;
}
return [UIColor whiteColor];
}
ダークモード対応のUIColorのプロパティ systemBackgroundColor などは UIColor(英文) ではなく UI Element Colorsドキュメント(英文)に載っています。
UIColor のページには UI Element Colors を見ろと書いてはありますが、見つけにくく不親切ですね。Swift言語を使う場合でも気づきにくいです。
宣伝ですが初級向け記事ですがnoteを書いています:iOSアプリを作ろう・資料の探し方読み方
ADCのドキュメント構成が変わって自分自身も戸惑ったので書いた記事です。Objective-Cでアプリを作っていた方で最近メンテナンスに迫られている場合にはお役にたつかもしれません。
ラベルは labelColor や secondaryLabelColor、背景は systemBackgroundColor や secondarySystemBackgroundColor などを使うことでダークモード対応となります。
カスタム色の対応
カスタム色をコードで指定する場合には現在ダークモードなのかの確認が必要でした。
次のように関数に引数で view のインスタンスを渡し UIUserInterfaceStyleDark か判別しました。
// 関数定義割愛
UITraitCollection *trait = view.traitCollection;
if (UIUserInterfaceStyleDark == trait.userInterfaceStyle) {
return [UIColor colorWithHue:130/360. saturation:1.0 brightness:0.18 alpha:1.0];
}
// 以下割愛
カスタム色をダークモード用にするにはカラーアセットが便利ですが、古いアプリだったので今回は colorWithHue:saturation:brightness:alpha: を使いました。
カラーアセットを使う場合、ダーク用のアセットを追加するとコードの変更は不要です。
なお brightness を変えただけでは実際の表示で黒と区別ができなかったので saturation の値も変えました。
モード切り替え対応
テーブルのセルの背景でカスタム色を使っているため、実行中にダークモードを変更されると再表示が必要でした。
UITableViewController を継承しているクラスでは次のコードのようにtraitCollectionDidChange: メソッドを追加するだけです。
// ダークモード切り替えで再表示
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
[self.tableView reloadData];
}
traitCollectionDidChange:はプロトコルのメソッドなのでiOS13で切り分ける必要はありません。
UIViewController や UIView は UITraitEnvironment プロトコルに準拠しています。
ステータスバー
WWDCのセッションでも UIStatusBarStyleDefault は自動でダークモードに対応しているとの説明がありました。
// UIStatusBarStyleDefaultは自動でダークモードに対応
setStatusBarStyle(UIStatusBarStyleDefault);
UIStatusBarStyleLightContent を指定している部分と一部の UIStatusBarStyleDefault で指定している部分でiOS13の切り分けが必要でした。
表示テスト中のダークモード切り替え操作
ダークモード対応の確認にはモードの切り替えが頻繁に必要です。
Xcode11とiOS13それぞれ便利な機能が追加されています。
確認する画面が多い場合は特に重宝する機能です。
シミュレータ実行中はXcode11の『Environmet Overrides』機能が強力で多用しました。実機でもXcode11から実行した場合は機能しました。
Environmet Overrides ボタンは実行中のみ表示されます。
実機はコントロールセンターの「ダークモード」が利用できます。iOS13ではコントロールセンターの設定で追加できます。
ワンタッチで切り替えることができ便利です。
この機能はプログラマ向けではないので、いつでもモードが切り替えられる前提でアプリ側での再表示対応は必須ですね。
ダークモード以外で変更が必要だった部分
UISegmentedControl の文字の余白寸法が変更になり、iOS12までは正常に表示されていたものが次の画面のように省略表示になってしまいました。
セグメントの幅をぎりぎりに指定している部分だけこの現象がでました。
iOS13の場合だけ幅を変更し対応しました。
ちなみにiOS9.3ではこのように表示していました。
修正後のダークモード表示はこうなりました。
そのほかiPadのポップオーバーで一部余白の調整が必要でした。これは古いコードの問題と思います。
今回のアプリはiPadのサイズがまだ1種類だけの時代に作ったiPhoneとiPad両用のアプリです。(さすがにiOS7には対応済みですがかなり古いです)
64bit対応でも手をいれています。ポップオーバーは昔とは別物になってますね。
ダークモードのドキュメント
私の場合はWWDCのセッションだけで情報は十分でしたが、ダークモード対応に関係するドキュメントはこちらにありました。
Supporting Dark Mode in Your Interface(英文)
このドキュメントは言語をObjective-Cに切り替えてもコードの部分はSwiftのものを表示しています。
Framework は AppKit となっていますが、macOSとiOS共通のドキュメントです。
Obj-CプログラマはSwiftとどう付き合うか
WWDCのスライドでのコードやサンプルがほとんどSwiftになってしまった現在、Objective-CつかいにとってもSwift対応(少なくともサンプルを読むには)は待った無しです。
宣伝ですが(笑)Appleのブックストアから『Swift5初級ガイド』をリリースしました。
Swift5.1の変更点は次の無料アップデートで対応予定です。
ブックストアで購入した電子書籍はほぼリアルタイムで無料アップデートが読めるので安心です。
サンプルは無料ですが、こちらの記事にページのサンプル表示などを確認できます。
おしらせ
私の活動内容はこちらをご覧ください。
iOSアプリ作りをアシストするセミナーは今後も月一回のペースで続ける予定です。
詳細は connpass.com の 札幌Swiftでご確認ください。そして機会があればぜひ参加してください。
アプリ作りやプログラミング教育に関連する話題は 札幌Swift のfacebookページで発信しています。
ここから先は
¥ 100
Amazonギフトカード5,000円分が当たる
今後も記事を増やすつもりです。 サポートしていただけると大変はげみになります。