MacOSアプリのメニューアイテムをSwiftUIで消すには?

1 min read読了の目安(約1600字

SwiftUIでMacOS向けのアプリを開発していてメニューアイテムを消したいときの方法をご紹介します。

この方法は@mainAppの方に置いている場合も有効です。

何はともあれ設定

下準備をしていきます。
早速ですが、エントリーポイントに以下のコードを追加しましょう。

こうすることで、Appが@mainでもAppDelegateのコードを書けるようになります。
@mainがAppDelegateの場合は何も追加しなくてよいでしょう。

import SwiftUI

@main
struct NiceApp: App {
    // これを追加
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

    var body: some Scene {
        // 何か書いてある
    }
}

メニューアイテムを消す

あとは、AppDelegate内のapplicationDidFinishLaunchingで以下のコードを書けば消えます。

NSApplication.shared.mainMenu?.items に現在のメニューアイテムが並んで格納されています。あとはその添字を指定すればあれこれ制御可能です。

isHiddenではなく、NSApplication.shared.mainMenu?.removeItem(at: xxx) で消してしまう方法もありますが、それだと添字が途中でずれるのでわかりにくためisHiddenで隠すようにしています。

class AppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate {
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        //        "アプリ名が書いてあるメニュー" 0
        //        "ファイル" 1
        //        "編集" 2
        //        "フォーマット" 3
        //        "表示(ビルトインの表示)" 4
        //        "ウインドウ" 5
        //        "ヘルプ" 6
        NSApplication.shared.mainMenu?.items[2].isHidden = true
        NSApplication.shared.mainMenu?.items[3].isHidden = true
        NSApplication.shared.mainMenu?.items[4].isHidden = true
        NSApplication.shared.mainMenu?.items[6].isHidden = true
    }
}

余談

アプリによっては「編集」メニューとか全然いらないよ!ってケースもたくさんあると思うのですがSwiftUIのCommandsだとそこまで細かい制御ができないみたいですね。

多分、そのうちできるようになるとは思うのですが、今時点では上記みたいなやり方が必要そうです。もし、もっとイケてる方法があるよって方はツッコミお待ちしてます。

SwiftUIを使わなければStoryBoardであれこれ調整するんでしょうが、私はSwiftUIで開発を開始して、いまさら引くに引けない状況になってしまったため、SwiftUIで突っ走ることを決意したのでありました。