SwiftUIでmacOS14から利用できるSettingsLinkの背景色を変更する

macOS 14.xで設定画面を開く仕様が変わりました。
macOS 13.xではNSApp.sendAction()showSettingsWindow:を呼ぶことで設定画面を開いていましたが、macOS 14.xではSettingsLinkを使って設定画面を開きます。
下記は使い方の例です。

// macOS 13.x
Image(systemName: "gearshape.fill")
    .onTapGesture {
        NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
    }

// macOS 14.x
SettingsLink {
    Image(systemName: "gearshape.fill")
}

SettingsLinkの公式ドキュメントはこちらです。

developer.apple.com

私も個人で開発しているMac向けのアプリで、macOS 14.xからの新しい仕様に対応すべくソースコードを修正したのですが、いざビルドしてアプリを実行してみると、問題が見つかりました。

SettingsLinkを適用した部分の背景色が変わった

SettingsLinkを適用したのは歯車アイコンなのですが、その背景色が変わってしましました。

歯車アイコンにSettingsLinkを適用したときの様子

実装したソースコードの抜粋は以下の通りです。

SettingsLink {
    Image(systemName: "gearshape.fill")
        .foregroundColor(Color(bodyForegroundTheme))
}

期待としては背景色は変わって欲しくなく、メニューバーを同じ薄緑色であって欲しかったです。とはいえ、デフォルトの背景色でこうなるだけなのだろうと思いました。それなら、background(Color.clear)などで背景色を無色にすればOK!と、いろいろ試したのですが、背景色を全く無色にできませんでした。

SettingsLink {
    Image(systemName: "gearshape.fill")
        .foregroundColor(Color(bodyForegroundTheme))
        .background(Color.clear) //<- 変わらない
}
.background(Color.clear) //<- 変わらない

SettingsLinkはButton?

そして、Google検索したところSettingsAccessというSwiftパッケージを見つけました。

github.com

早い話、このパッケージをそのまま使っても良かったのですが、README.mdを読んでみると以下の部分が目に止まりました。

SettingsLink is a view that wraps a standard SwiftUI Button and its action calls a private environment method called _openSettings which we have no access to publicly. (A radar has been submitted asking Apple to make it public, but until that happens - if ever - SettingsAccess is the solution.)

意訳すると、

  • SettingsLinkはSwiftUIのButtonのラッパーである
  • SettingsLinkはopenSettingsというメソッドを呼んでいるが、openSettingsに外からアクセスする手段はない
  • openSettingsをpublicにするようAppleにリクエストが出ている

大事なのは、SettingsLinkはSwiftUIのButtonのラッパーであるであり、もしかしたらButtonStyleで背景色を無色にできるのではないか?と考えました。

ButtonならButtonStyleで変更してみる

まず、ButtonStyleを定義します。SettingsLinkStyle.swiftファイルを作り、そこに記述しました。

import SwiftUI

struct SettingsLinkStyle: ButtonStyle {

    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(.clear)
    }
}

そして、SettingsLinkにSettingsLinkStyleを適用します。

SettingsLink {
    Image(systemName: "gearshape.fill")
        .foregroundColor(Color(bodyForegroundTheme))
}
.buttonStyle(SettingsLinkStyle())

ビルドして確認してみると、背景色を無色に変更できました。

SettingLink適用の歯車アイコンの背景色が無色になった

今回は無色にしましたが、実際は他の色も適用できます。
正直、これが正しい方法かわかりませんが、参考までに。

ブログ中で使ったソースコードは個人開発しているMac向けのメニューバーからアクセスするノートアプリMizuameのものです。MITライセンスのオープンソースですので、実際のソースコードはこちらから確認できます。

github.com

AppStoreにも公開しています。
広告は好きではないので付いてません。

Mizuame

Mizuame

  • Akira Nakamura
  • ユーティリティ
  • 無料
apps.apple.com