[SwiftUI][macOS] About Window のカスタマイズ方法

SwiftUI2021

     

TAGS:

⌛️ 3 min.

SwiftUI で macOS アプリの “About Window” を作る方法をまとめます

環境&対象

以下の環境で動作確認を行なっています。

  • macOS15.0.1 Sequoia
  • Xcode 16.1 Beta
  • iOS 18.1
  • Swift 5.9

AboutWindow

macOS でのアプリで、ツールバー上のアプリ名のメニューの直下にある “あれ” です。

Xcode には、以下のようなメニューがあります。

AboutAppMenu

選択すると以下のようなウインドウが表示され、アプリケーション名やバージョン番号等の情報が表示されます。

SwiftUINomarlWindow

SwiftUIアプリでのデフォルト

macOS 向けアプリを SwiftUI を使用して作成すると、メニューは自動で作成され、以下のようなウィンドウも表示されます。

XcodeAboutWindow

おそらく、AppIcon のデータと、バージョン番号/ ビルド番号を取得して表示しているものと思われます。

独自の AboutWindow

WWDC24 のビデオをみると、簡単に独自の AboutWindow を表示できそうだったので、調べて見ました。

ですが、別にショートカットが用意されているわけではありませんでした・・・orz

大きく分けると2つのステップに別れます。

・”About My App” メニューの置き換え
・”About My App” ウィンドウの設定

“About My App” メニューの置き換え

SwiftUI2024 で追加されたあたらしい .commandsReplaced を使用して置き換えます。

SwiftUI2021 [SwiftUI] commands Modifier @SwiftUI(2024)

MEMO

WWDC24 のビデオを見ていた時には、Window の id 指定で “About Window” を置き換えられるかと想像したのですが、違いました。
コツコツ(?) と置き換える必要がありました・・・

以下のように、commandsReplaced を使用して .appInfo を置き換えることで、 “About <アプリ名>” のメニューを置き換えることができます。

import SwiftUI

@main
struct AboutWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commandsReplaced(content: {
            CommandGroup(replacing: .appInfo, addition: {
                Button(action: {
                    // show my own window for about window
                }, label: { Text("About My App") })
            })
        })
    }
}            

CommandGroup 中の Button の label で指定したものが、メニューに表示されますので、特に “About My App” という表示でなくとも技術的には問題ありません。

# ただし、AppStore で Review されるときにどのように扱われるかは分かりません。

“About My App” ウィンドウの設定

メニューを置き換えることができましたので、ウィンドウを定義して、表示できるようにしていきます。

ウィンドウ定義

まずは、ウィンドウを定義します。

アプリに新しいウィンドウを定義するには、Window を使います。

参考
WindowApple Developer Documentation

以下のように App の body 内に追記することで、アプリのウィンドウを追加できます。

import SwiftUI

@main
struct AboutWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commandsReplaced(content: {
            CommandGroup(replacing: .appInfo, addition: {
                Button(action: {
                }, label: { Text("About My App") })
            })

        })
        Window("About MyApp", id: "about", content: {
            // AboutWindow content  
        })
    }
}

ドキュメントを確認すると分かりますが、第1引数は ウィンドウタイトル、第2引数はウィンドウID、第3引数は ウィンドウ表示要素 です。

こちらのビデオでお勧めしている ViewModifier 等も指定して以下のようにしました。

import SwiftUI

@main
struct AboutWindowApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commandsReplaced(content: {
            CommandGroup(replacing: .appInfo, addition: {
                Button(action: {
                }, label: { Text("About My App") })
            })
        })
        Window("About MyApp", id: "about", content: {
            VStack {
                Image(systemName: "function").resizable().scaledToFit().frame(width: 100, height: 100)
                Text("My App").font(.largeTitle).bold()
                Text("Version ♾️ (♾️)")
            }
            .padding(32)
            .toolbar(removing: .title)
            .toolbarBackground(.hidden, for: .windowToolbar)
            .containerBackground(.thickMaterial, for: .window)
            .windowMinimizeBehavior(.disabled)
        })
        .windowResizability(.contentSize)
        .restorationBehavior(.disabled)
    }
}

それぞれの ViewModifier の意味は、上記のビデオで確認してください。

ウィンドウを開く

先ほど定義したウィンドウを 最初に定義したメニューに紐づけて、開くことができるようにします。

具体的にはメニューで設定した Button の action を使って開くようにします。

SwiftUI では ウィンドウを開くために、OpenWindowAction が用意されています。


参考
OpenWindowActionApple Developer Documentation

そしてその OpenWindowAction は Environment として 使用できるようになっています。


参考
openWindowApple Developer Documentation

ということで、その openWindow を Button の action から使用すると 該当IDを持つウィンドウを開くことができます。

import SwiftUI

@main
struct AboutWindowApp: App {
    @Environment(\.openWindow) var openWindow
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .commandsReplaced(content: {
            CommandGroup(replacing: .appInfo, addition: {
                Button(action: {
                    openWindow(id: "about")
                }, label: { Text("About My App") })
            })
        })
        Window("About MyApp", id: "about", content: {
            VStack {
                Image(systemName: "function").resizable().scaledToFit().frame(width: 100, height: 100)
                Text("My App").font(.largeTitle).bold()
                Text("Version ♾️ (♾️)")
            }
            .padding(32)
            .toolbar(removing: .title)
            .toolbarBackground(.hidden, for: .windowToolbar)
            .containerBackground(.thickMaterial, for: .window)
            .windowMinimizeBehavior(.disabled)
        })
        .windowResizability(.contentSize)
        .restorationBehavior(.disabled)
    }
}

以下のような挙動になります。

AboutWindow として表示されている ウィンドウは、普通(?) のSwiftUI のビューですので、ここ以降のカスタマイズは SwiftUI で普通にできます。

まとめ

About Window のカスタマイズ方法を確認しました。

About Window のカスタマイズ方法
  • commandsReplaced と CommandGroup(replacing:) を使って置き換える
  • 置き換えるのは、.appInfo
  • ウィンドウをプログラム的に開くのは、Environment の openWindow を使用する

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

SwiftUI おすすめ本

SwiftUI を理解するには、以下の本がおすすめです。

SwiftUI ViewMatery

SwiftUI で開発していくときに、ViewやLayoutのための適切なmodifierを探すのが大変です。
英語での説明になってしまいますが、以下の”SwiftUI Views Mastery Bundle”という本がビジュアル的に確認して探せるので、便利です。

英語ではありますが、1ページに コードと画面が並んでいるので、非常にわかりやすいです。

View に適用できる modifier もわかりやすく説明されているので、ビューの理解だけではなく、どのような装飾ができるかも簡単にわかります。

超便利です

SwiftUIViewsMastery

販売元のページは、こちらです。

SwiftUI 徹底入門

# SwiftUI は、毎年大きく改善されていますので、少し古くなってしまいましたが、いまでも 定番本です。

Swift学習におすすめの本

詳解Swift

Swift の学習には、詳解 Swift という書籍が、おすすめです。

著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。

最新版を購入するのがおすすめです。

現時点では、上記の Swift 5 に対応した第5版が最新版です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です