メニューバーの「File」に「New Tab」の項目を追加する

Xcode Version 16.1 (16B40) を使用しています。

# サンプルの準備

新規プロジェクト → macOS → App でプロジェクトを作り ContentView の中身を移動してファイルを1つにします。

![Sample0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/3fcae7e4-6ac0-7a30-56b6-ad60ea328ef1.png)

# サンプルの実行と変更

Xcode で Command+R でコンパイルして実行する

![Sample1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/2292fc33-7f23-169e-7ee6-7dbf34c842bc.png)

### メニューバーの "File" には新規タブで開く項目はありません

![Sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/4463286b-4276-236e-0524-d4ebf0a8d352.png)

### メニューバーの "View" を開きます

![Sample3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/6e6cc97b-a1e9-960e-459b-44f2e3d9d916.png)

タブに関する項目が出てきました。

### "Show All Tabs" を突いてみる

![Sample4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/c9bce7d5-530e-2617-1b55-3d9201df8832.png)

新規でタブが足せる…

### "Show Tabs Bar" を突いてみる

![Sample5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/02559c2f-0874-008e-0165-63aa7b3e9174.png)

こっちでも右上の "+" でタブが足せる…

タブ機能を有効活用するなら "File" に "New Tab" があった方がよさそうですが、デフォルトでは用意されてません。


# "File" に "New Tab" を足す

"New Window" は [openWindow](https://developer.apple.com/documentation/swiftui/environmentvalues/openwindow) で開く方法がありますが、これに準じる方法で "New Tab" する方法を見つけることができませんでした。NSWindow に ContentView を割り当てる方法が彼方此方にありますが、それだと App の body 定義が使用されません。メニューバーの "View" 操作経由のタブ追加では body 定義が有効です。

試しに openWindow や NSApplicationDelegate.applicationOpenUntitledFile で作った新規ウインドウをタブ グループに追加したら想定した動作になりました。


```swift:SampleApp.swift
import SwiftUI

@main
struct SampleApp: App {
    @Environment(\.openWindow) private var openWindow

    var body: some Scene {
        WindowGroup(id: "hello-world") {
            ContentView()
        }
        .commands {
            // メニュー バーの "File" に "New Tab" を追加
            //   ショートカットに Command+T を設定
            CommandGroup(before: .newItem) {
                Button("New Tab") {
                    openNewTab()
                }
                .keyboardShortcut("T", modifiers: [.command])
            }
        }
    }

    // 新規タブを開く
    private func openNewTab() {
        guard let keyWindow = NSApp.keyWindow else { return }
        guard let tabGroup = keyWindow.tabGroup else { return }
#if true
        guard let appDelegate = NSApp.delegate else { return }
        guard let openUntitledFile = appDelegate.applicationOpenUntitledFile else { return }
        if !openUntitledFile(NSApp) { return }
#else
        openWindow(id: "hello-world")
#endif
        // 追加される新規ウインドウは最後に存在すると推測
        guard let window = NSApplication.shared.windows.last else { return }
        // そのままだと独立ウインドウで現れるので tabGroup への追加を試みる
        tabGroup.addWindow(window)
    }
}

struct ContentView: View {
    static private var viewIndex: Int = 1
    static private var viewCount: Int = 0
    @State private var viewTitle = "Hello, World! (\(ContentView.viewIndex))"

    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text(viewTitle)
        }
        .navigationTitle(viewTitle)
        .padding()
        .onAppear {
            ContentView.viewIndex += 1
            ContentView.viewCount += 1
        }
        .onDisappear {
            ContentView.viewCount -= 1
            if ContentView.viewCount == 0 {
                // 全てのウインドウを閉じたら終了
                NSApplication.shared.terminate(nil)
            }
        }
    }
}

#Preview {
    ContentView()
}
```

---

こんな方法でいいのか甚だ疑問だけど...