4
3

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 5 years have passed since last update.

[macOS][Swift4.2] MacアプリでMojaveの外観モード切り替えに対応する

Last updated at Posted at 2019-03-11

macOS 10.14 Mojaveでは外観モード(=システム全体のUIの見栄え)を従来通りの明るい ライト 、新しく追加された暗めの ダーク に切り替えることができるようになった。
ダークモードによって、眼精疲労がかなり軽減されたので非常に重宝している。
WebViewの内容も切り替わったら嬉しいのに。

この外観モードを切り替えた時、Macアプリでどのように対応したら良いのか記載したい。
標準のUIコンポーネントのみで構成されたアプリであれば、Xcode10以降でビルドすれば特に対応の必要がなく自動的に再描画してくれる。(*)
しかし、自前のビューを配置していたり直接描画していたりする場合、標準コントロールだけが別のモードになって、自前ビューの部分が切り替わらず描画バグっぽく見えてしまうことがあるので対応の必要が出てくる。

* Xcode9以前でビルドされたバイナリでは従来通り強制的にライトのみのサポートになる模様。


  • Xcode10.1
  • Swift4.2
  • macOS Mojave 10.14.2

外観モードを変更するには?

システム環境設定 > 一般に「外観モード」があり、ライトかダークが選択できるようになっている。
system_settings.png

外観モードの取得

システムで設定されている外観モードは以下で取得することができる。

let appearance = NSApplication.shared.effectiveAppearance

判定は NSAppearance.name でできそうだ。
ライトなら .aqua 、ダークなら .darkAqua となっている。(まだアクアだったのか。。)

switch NSApplication.shared.effectiveAppearance.name {
case .aqua:
    print("外観モードはライト")
case .darkAqua:
    print("外観モードはダーク")
default:
    assertionFailure()
}

外観モードの指定

NSApplication.shared.appearanceNSAppearance をセットすることでシステムでの設定に代わり、指定した外観モードが採用されるためシステムでの外観モード変更に左右されない。
両方対応すると開発・デザインともにコストがかかるのでどちらかしか対応したくない場合はこの方法を使って固定値としておけば良い。

// 外観モードをライトのみサポートする
NSApplication.shared.appearance = NSAppearance(named: .aqua)

外観モードが変更された時のハンドリング

NSView.viewDidChangeEffectiveAppearance() が使える。
オーバーライドしておけば外観モードが変更された時に呼ばれるので effectiveAppearance に応じて描画内容を変更して再描画すればOK。

HogeView.swift
override func viewDidChangeEffectiveAppearance() {
    print(NSApplication.shared.effectiveAppearance.name)
}

macOS 10.13以前

外観モードはmacOS 10.14以降しか使えないので両方対応する場合、if分岐しておき10.13以前は NSAppearance.Name.aqua の場合と同様の処理に流れるようにしておくと良い。

HogeView.swift
func setupAppearance() {
    func setupForLight() {
        textColor = .black
        backgroundColor = .white
    }
    func setupForDark() {
        textColor = .white
        backgroundColor = .black
    }

    if #available(macOS 10.14, *) {
        switch NSApplication.shared.effectiveAppearance.name {
        case .aqua:
            setupForLight()
        case .darkAqua:
            setupForDark()
        default:
            assertionFailure()
        }
    } else {
        setupForLight()
    }
}

Supporting Dark Mode in Your Interface

4
3
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
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?