Swift UIのSettingsLinkで設定を開くと、画面が最前面にならない

以前に投稿したこちらの記事では、私個人で開発しているMacアプリで、macOS 14から使うことができるSettingsLinkの対応を行いました。というのも、macOS 14からは設定画面を開く仕様が変更され、SettingsLinkを使用しなければならないからです。

a3colorr.hatenablog.com

実は、このときに先送りしていた問題がありました。
それは、SettingsLinkで設定画面を開くと、自分自身(アプリ自身)がアクティブ状態のときだけ、設定画面が最前面に表示されることです。どんな挙動かというと以下のGIFの通りです。

アプリ自身がアクティブだと最前面に、非アクティブだと背面に設定画面が表示される
自身が非アクティブ状態のときは背面になる

何が問題なのか?

通常のウインドウを持つアプリ(例:ブラウザ、メモ帳など)であれば、使用している間は常にアクティブ状態なのでSettingsLinkを使って設定画面を開いても期待通りに最前面に表示されると思います。
しかし、私が開発しているアプリは上記の通り、メニューバーからシュッと出てくるアプリです。そのため、メニューバーからシュッと出したときでも他のアプリがアクティブ状態になっているという現象が見られます。この現象があるために、設定画面が最前面に表示されなくなります。

macOS 13以前はどうしていたか?

macOS 13以前では、設定画面を開くボタンを押したときのイベントでNSApp.activate(ignoringOtherApps: true)を実施することで最前面に表示させていました。しかし、SettingsLinkは特殊なButtonであり、通常のButton(label:, action:)のうちaction:に相当する部分が実行されないようです。onTapGestureも試しましたがダメでした。

ではそうしたか?

正解かどうかか分からないですが、メニューバーからアプリを表示させるメソッドNSPopover.show()に続いて、NSApp.active(ignoringOtherApps: true)を呼び出すことで、今のところ期待通りに、設定画面が最前面に表示されました。

実装例

// メニューバーからアプリを表示する
@objc func showPopover(sender: NSStatusBarButton) {
    if currentEvent.type == NSEvent.EventType.rightMouseUp {
        // 右クリックの処理

    } else if currentEvent.type == NSEvent.EventType.leftMouseUp {
       // 左クリックの処理=アプリを開く
       popover.show(なんとかかんとか)
    }

+ NSApp.activate(ignoringOtherApps: true)
}

実際の実装

github.com

これ以外にも、onHoverを使った方法も試しました。歯車アイコン(Image(systemName: "gearshape.fill"))をクリックするときは、期待通り、設定画面が最前面に表示されたのですが、ショートカットキーcommand + ,のときは他のアプリの背面に表示されてしまいました。

SettingsLink {
    Image(systemName: "gearshape.fill")
}
.onHover { _ in
    NSApp.activate(ignoringOtherApps: true)
}




ちなみに、個人開発しているMacアプリはこちらになります。もしよろしければ試してみてください。

Mizuame

Mizuame

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

このMacアプリ MizuameはMITライセンスでソースコードを公開しています。

github.com