5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ダークモード対応の罠

Last updated at Posted at 2020-08-17

去年iOS 13の新機能で出たダークモードを自社アプリに対応したのですが、思わぬ挙動でバグが出てしまいそのTips共有です

traitCollectionDidChangeの罠

ライト⇄ダークの色切り替え時に特定の処理を行いたい場合は
func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
を使って切り替え時の検知ができます

単純にライト/ダーク時に専用の配色を入れる(例 CGColorで色を入れる必要がある)場合は問題ないですが、それ以外の何か別の設定を入れる(例 ダークモードの時だけ〇〇する)みたいなケースだと問題がおきます

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        
    super.traitCollectionDidChange(previousTraitCollection)
        
    if UITraitCollection.current.userInterfaceStyle == .dark {
        // ダーク時だけしたい処理
    }
        
}

コントロールセンターのライト→ダークに切り替え時に traitCollectionDidChange
が呼ばれるのですが、 バックグラウンドに入った瞬間にtraitCollectionDidChangeが2回呼ばれます(ライト⇄ダーク切り替えなしに)

しかも、ただ2回呼ばれるのではなくバッググラウンドに入った時に、今端末がライト/ダークどっちの設定が入っているかを確認できる UITraitCollection.current.userInterfaceStyleがライトとダークそれぞれの状態で来ます

本来ダークモード設定の時だけしたい処理がバックグラウンド時にライトとダークそれぞれ来ることになり、端末設定がライトモードの時でもダークモード時にしたい処理をしてしまう、期待外れなことが起きてしまいます😇

この挙動がよくわからず・・・
ちなみに他のライフサイクルでの検知できるメソッドだとどうか?
同様の問題が起きてダメでした・・

  • viewWillLayoutSubviews
  • viewDidLayoutSubviews 

など

回避策

個人的にあんまり納得いく修正方法ではありませんが、バッググラウンド時は特定の処理までしないようにしました
バックグラウンド上で設定を変えてもフォアグラウンドに戻った時呼ばれるので問題ないです

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        
    super.traitCollectionDidChange(previousTraitCollection)
    
    if UIApplication.shared.applicationState == .background {
        return
    }
    
    if UITraitCollection.current.userInterfaceStyle == .dark {
        // ダークの時のみしたい処理
    }
        
}

なぜ今回の問題になった挙動をするかいまいちわかってないのでうーんっていう気持ちで修正できました()

おまけ traitCollectionDidChangeで色を入れるのは大丈夫なの?

大丈夫です
ライトモード時はライト、ダークモード時はダークの色を入れてくれます(最終的に)
試しにアセットカタログのファイルで以下の色を用意して
スクリーンショット 2020-08-17 14.39.24.png

  • UITraitCollection.current.userInterfaceStyle

の要素をログで追って確認し、ライトモードでバッググラウンド時に入ってみて検証してみました

dark

Optional([1.0, 1.0, 1.0, 1.0])

light

Optional([0.0, 0.0, 0.0, 1.0])

2回呼ばれますが、
ライトモードだとダーク→ライトの順番に呼ばれるので最終的にライトの色が入ります
同様にダークモードでも ライト→ダークと呼ばれダークの色が入るので大丈夫です

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?