2019年6月29日土曜日

iOS13: Dark Modeの対応方法

アプリのiOS 13対応 で、必ず通るのが Dark Mode対応。
なぜなら、Opt-out だから。

まだ iOS 13 beta2 なので、今後変わるかもしれないけど、今の知見を書いてみる。

Dark Mode にしない設定

XCode 11でビルドしたアプリを、iOS 13でみるとDark Mode対応になる。
XCode 10以下でビルドしたものは、Dark Modeにはならない。(Light Mode)

アプリ全体でModeを固定にしたい場合は、plistのUIUserInterfaceStyleで指定可能。
特定の画面でModeを固定にしたい場合は、overrideUserInterfaceStyle で指定可能。


Modeごとの色

System Color

Light / Dark でよきに変わるシステムカラーが利用できる。
Human Interface Guidelines: System Color

ラベル文字色、背景色などごとに、Primary, Secondary, Tertiary の色が用意されているので重要度に合わせて使う。
UI Element Colors

Dark ModeのときのsystemBackgroundは基本的にはUIColor.black だが、Page SheetなどのModalのときは、少し薄い黒になることに注意。

System ColorはiOS 13以上で利用可能なため、コード上で設定するにはiOS 13 以上である必要がある。
if #available(iOS 13.0, *)  {
    titleLabel.textColor = UIColor.label
}
ただ、StoryboardにてSystem Colorを設定した場合は、iOS 12でも利用可能。

Backwards compatibility for iOS 13 system colors は下位互換のための情報の良記事。

Custom Color

独自の色は、Asset CatalogでColors Set を指定して利用する。
コードから利用したいときには、UIColor(named: "colorName")  で。


Mode切替のタイミングの判定

Light / Dark は、システムによって動的に変わる場合がある。
(Settings > Display & Brightness に Automatic の切替アリ)

UIViewやUILabelなどは自動的に切り替わるので特に考慮は必要ないが、cocoa 2D などでコードで色を指定しつつ描画しているところなどは、切替のタイミングを判定して描画し直す必要がある。

切替のタイミングは、traitCollectionDidChange

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)
    let userInterfaceStyle = traitCollection.userInterfaceStyle
}

UIUserInterfaceStyle のEnumに、unspecified, light, dark が定義されている。

traitCollectionDidChangeはデバイスの回転などでも呼び出されることに注意。
Mode切替の場合のみ処理したい場合には、hasDifferentColorAppearance を使って判定できる。

let hasChanged = previousTraitCollection.hasDifferentColorAppearance(comparedTo: traitCollection)

Color Setの色から、現在のModeの色を取得するには、resolvedColor(with:) を使う。
let color = UIColor(named: "MyColor")?.resolvedColor(with: traitCollection)


• • •