SwiftUI を使えば、メニューバーアプリケーションを簡単に開発できます。
メニューバーアプリケーションを設置することで、最上部システムバーにアプリケーションが表示され、ユーザーはこのアイコンをクリックしてアプリケーションのポップオーバー表示にすばやくアクセスできるようになります。
アプリレビューを待つ間に、システムバー内でタスクリストを管理できる小さな TODO アプリケーションを最近開発しました。ソースコードをダウンロードして仕組みを確認することができます。
https://github.com/mszmagic/MenuBarTODO
https://apps.apple.com/jp/app/menubartodo/id1550343840?mt=12
MacOSアプリケーションの作成
まず、SwiftUIを有効にした空のMacOSアプリケーションを作成します。アプリケーションの種類として AppKit App Delegate
を選択していることを確認してください。
AppDelegate.swift
ファイルの設定
メニューバーアイテムとポップオーバーウィンドウをこのファイルで設定する必要があります。この記事では、ContentView()
をポップアップウィンドウとして使用します。
アプリケーションで一般的なインターフェースも使用したい場合には、ポップアップウィンドウ専用の個別のSwiftUIビューを作成する必要があります。
変数の設定
以下の変数を AppDelegate.swift
ファイルに追加:
var statusBarItem: NSStatusItem!
var popover: NSPopover!
ステータスバーのアイテムを初期化する
statusBarItem
は、システムのメニューバーに表示される項目です。このオブジェクトをイメージ(またはシステムイメージ)で初期化する必要があります。
self.statusBarItem = NSStatusBar.system.statusItem(withLength: CGFloat(NSStatusItem.variableLength))
guard let button = self.statusBarItem.button else { return }
button.image = NSImage(systemSymbolName: "checkmark.circle.fill", accessibilityDescription: nil)
button.action = #selector(showHidePopover(_:))
この記事の次の部分で showHidePopover
関数を定義します。
ポップオーバーを初期化する
ここで、ポップオーバーウィンドウを初期化して、そのウィンドウのコンテンツとなるSwiftUIのビューを設定する必要があります。
let popover = NSPopover()
popover.contentSize = NSSize(width: 350, height: 500)
popover.behavior = .transient
let contentView = ContentView().environment(\.managedObjectContext, persistenceController.storageContext)
popover.contentViewController = NSHostingController(rootView: contentView)
self.popover = popover
ユーザーがメニュー項目をクリックした際にポップオーバーを表示または非表示
また、ポップオーバーを表示または非表示にする機能 showHidePopover
も定義する必要があります。
@objc func showHidePopover(_ sender: AnyObject?) {
guard let button = self.statusBarItem.button else { return }
if self.popover.isShown {
self.popover.performClose(sender)
} else {
self.popover.show(relativeTo: button.bounds, of: button, preferredEdge: NSRectEdge.minY)
self.popover.contentViewController?.view.window?.becomeKey()
}
}
プログラムを実行する
これでプログラムが実行できます。システムメニューバーに新しいメニュー項目が表示されるはずです。
システムメニューバーにしか表示されないアプリケーションの作成
Xcodeでプロジェクトを作成すると、XcodeではSwiftUIのビューがウィンドウに表示されます。
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
// Create the window and set the content view.
window = NSWindow(
contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
backing: .buffered, defer: false)
window.isReleasedWhenClosed = false
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
}
window
変数を削除し、applicationDidFinishLaunching
関数内のすべての関連コードを削除する(メニュー項目とポップオーバーを初期化するためのコードは保持します)ことで、アプリケーションをシステムメニューバーでのみ表示するようにできます。
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView()
// ...
}
また、システムがアプリケーションウィンドウの表示を試みないようにするには、Info.plist
ファイル内のLSUIElement
をYES
に設定する必要があります。
ところでそのアプリケーションは、システムメニューバーにのみ表示され、アプリケーションウィンドウは表示しません。
Githubのこちらのデモプロジェクトをご覧ください。上記のコードが含まれています。
https://github.com/mszmagic/MenuBarTODO