iOS13 ダークモード対応と向き合ってみた

iOS 13.0以降ではダークモードに対応しているとみなされます。

> **Dark Mode**
> 
> In iOS 13.0 and later, people can choose to adopt a dark system-wide appearance called Dark Mode. In Dark Mode, the system uses a darker color palette for all screens, views, menus, and controls, and it uses more vibrancy to make foreground content stand out against the darker backgrounds. Dark Mode supports all accessibility features.
> 
> People can choose Dark Mode as their default interface style, and they can use Settings to make their devices automatically switch to Dark Mode when ambient light is low.

## System Colors, Dynamic System Colors (セマンティックカラー)を使う

System Colors, Dynamic System ColorsはiOS SDKで提供されているカラーセットに含まれる、システムで定義されたカラーです。これらのシステムカラーは現在のAppearanceに応じて自動的に対応します。

System Colorsは"Red"や"Blue"のように汎用的に使えるカラーとなっており、ダークモードの際には若干ですが暗めに色が変化します。

一方、Dynamic System Colorsはセマンティックカラーと呼ばれ、"systemBackground"や"label"のようにある程度特定のUIコンポーネントで使用されることを前提としています。

以下の例は、"view"の"backgroundColor"に"systemBackground"、"label"の"textColor"に"label"、"textView"の"textColor"に"label"を指定した場合のライトモードとダークモードの違いです。

<img width="1067" alt="スクリーンショット 2019-11-12 17.33.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/1589ba11-1058-6a5e-9563-3a04c6f03d74.png">

<img width="1068" alt="スクリーンショット 2019-11-12 17.38.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/3bb538bb-01c1-ceef-df4a-e1d113784904.png">

ダークモードの場合は、バックグランドカラーが白系から黒系に、テキストカラーが黒系から白系になっていることがわかります。

## Asset CatalogのColor Setでカラーを定義する

カスタムカラーが必要な場合は、Asset CatalogにColor Setを追加し、ダークモード対応のユーザー定義のカラーを作成するのがよいでしょう。

筆者はイメージ用のAsset Catalogとカラー用のAsset Catalogを別々で用意し、管理するようにしています。

<img width="1440" alt="スクリーンショット 2019-11-12 17.53.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/64b192f8-7909-599d-5449-2f9dfcc2b2b3.png">

<img width="1440" alt="スクリーンショット 2019-11-12 17.54.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/90d801e3-c6ad-2393-e2f6-c48276b64959.png">

Color Setを追加したら、Color Setの"Appearance"設定で、"Any, Light, Dark"を選択し、"Any"と"Light"にデフォルト(ライトモード時)のカラーを、"Dark"にダークモード時のカラーを設定します。

<img width="1440" alt="スクリーンショット 2019-11-12 18.41.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/051b5405-b623-6e97-8941-a5b5cdeeef94.png">

<img width="1440" alt="スクリーンショット 2019-11-12 18.56.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/bc26032d-ca39-4d53-de26-f574122de7af.png">

テキストカラーも定義してみます。ダークモード時には少し暗めの色にしています。

<img width="1440" alt="スクリーンショット 2019-11-12 19.00.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/125a283e-9998-c275-6689-a591655e3c6c.png">

## 定義したカラーを使う

定義したカラーはStroyboard, Xibから使用することができます。

<img width="942" alt="スクリーンショット 2019-11-12 19.04.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/53efff2c-0304-b16d-cc27-b569dd3bc05d.png">

"view"の"backgroundColor"に"Primary"、"label"の"textColor"に"Text"を設定した場合のライトモードとダークモードは以下のようになります。

<img width="941" alt="スクリーンショット 2019-11-12 19.05.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/38aaf8d8-1f06-2770-6b61-c6d34b4f925d.png">

<img width="941" alt="スクリーンショット 2019-11-12 19.06.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/c8e0c94a-be32-5f09-e36b-25fff93da957.png">

Color Setで定義した"Light"と"Dark"のカラーがApearanceに応じて適用されているのがわかります。

定義したカラーはコードからも使うことができます。

```Swift
let primary = UIColor(named: "Primary")
```

ちなみに、筆者が以前ご紹介したことのある[**"R.swift"**](https://qiita.com/UJIPOID/items/92320ba26ca742999855)といったライブラリを使うと、タイプセーフになるのでより利便性が向上します。

```Swift
let primary = R.color.primary()
```

## ダークモードの確認方法

Storybard, Xibの下部メニュー、"Interface Style"を切り替えることで簡易的にダークモードを確認することとができます。

<img width="809" alt="スクリーンショット 2019-11-12 20.24.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/ede01ef8-b4cb-78df-7b21-85b4077eee72.png">

シュミレータ実行中であれば、デバッグメニューから"Interface Style"を切り替えることで、アプリ起動中のリアルタイムなダークモード切り替えを確認することができます。

<img width="909" alt="スクリーンショット 2019-11-12 20.29.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151693/7293843e-e506-6b73-3cd6-18ac2453c4b6.png">

## おまけ

### 配色や色のコントラストを考える

Appleの"Human Interface Guidelines"では、色のコントラストにも言及されており、カスタムカラーの場合、特に小さいテキストの場合、コントラスト比7：1を目指しましょう、としています。

ダークモード対応にあたって、配色や色のコントラスにも気を配る必要が出てきたので、以下のようなツールをご紹介しておきます。

* [**"ColorDrop"**](https://colordrop.io/) : 配色のパターンを決めるのに役立つツール
* [**"CONTRAST CHECKER"**](https://contrastchecker.com/) : 色のコントラストが確認できるツール

### どうしてもダークモード対応したくないとき

Info.plistに"UIUserInterfaceStyle"というキーで"Light"を設定すると、アプリは常にライトモード扱いとなり、ダークモードにはなりません。ただ、こちらの方法はAppleのご機嫌次第では後々、申請時にリジェクト対象になったり、設定が非推奨になったりする可能性もあるので、この先もこの方法が使えるとは限りません。