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

[SwiftUI / MacOS]既存メニューバー項目を取り除く

Last updated at Posted at 2021-11-07

結論から

スクリーンショット 2021-11-07 15.38.44.png
MacOSのアプリケーションを作成するときにデフォルトで提供されているメニューバーを取り除きたくなる時があると思います.StoryBoardを利用する場合はサクッとできますがSwiftUIの機能だけではサクッとできません.そのため,StoryBoard時代の機能を経由してメニューバーからデフォルトの項目を取り除きます.

sampleApp.swift
import SwiftUI

@main
struct palmShortcutApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate  // ①
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

// ②
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        let rmMenuTitles = Set(["File", "Edit", "View", "Window", "Help"])
        
        if let mainMenu = NSApp.mainMenu {
            let menus = mainMenu.items.filter { item in
                return rmMenuTitles.contains(item.title)
            }
            for i in menus {
                mainMenu.removeItem(i)
            }
        }
    }
}

説明

上のコードをコピペするだけでOKですが,簡単に説明を書きます.

① SwiftUI時代のAppDelegate

ここでStoryBoard時代のAppDelegateを接続します.プロジェクトを作成する際にSwiftUIを選択した場合はAppDelegateがありませんので,自分たちで作成する必要があります.ただし,SwiftUIではファイルを作成する必要がありません.そのため,今回のようなメニューバーから特定の項目を削除するみたいな少ないコードは[App名].swiftの中に直接classを定義しても何ら問題はありません.

② class定義

ここがAppDelegateの本体になります.やっていることは単純です.

  1. 既存のメニューバーのタイトルを(手入力ですが)集合型で定義
  2. メニューバーの項目名をループし,項目名が集合に含まれていればメニューバーから削除する

ここで注意したいのが,このコードは英語版(つまりデフォルト)のメニューしか削除できないということです.レアケースだとは思いますが,プロジェクトを日本語化している人は最初の集合型の定義を日本語に書き直す必要があります.もちろん他の言語圏も同様です.

おまけ(メニューの追加)

既存のメニューを削除しましたが,オリジナルなメニューを追加したいこともあると思います.
その場合はSwiftUIの.commandsを利用すると良いです.

sampleApp.swift
import SwiftUI

@main
struct palmShortcutApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commands { // 追加
            CommandMenu("sample"){
                SampleCommand()
            }
        }
    }
}

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        let rmMenuTitles = Set(["File", "Edit", "View", "Window", "Help"])
        
        if let mainMenu = NSApp.mainMenu {
            let menus = mainMenu.items.filter { item in
                return rmMenuTitles.contains(item.title)
            }
            for i in menus {
                mainMenu.removeItem(i)
            }
        }
    }
}

// 追加
struct SampleCommand: View {
    var body: some View {
        Button("print Hello"){
            print("Hello")
        }
    }
}

すると以下のように既存のメニューが削除され,オリジナルのメニューだけになります.
スクリーンショット 2021-11-07 15.35.35.png

ご参考になれば幸いです.

参考

SwiftUIでは「既存メニュー項目に新しいメニューを追加すること」が簡単にできるようになっていますので,一般的なアプリケーションを作成する場合は.CommandGroup(replacing: .after)とかを有効活用すると良さそうです.

0
3
1

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
0
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?