🐰

NSDockTilePlugInを使って起動していないMac appのDockに任意のアイコン表示を行う

2023/10/09に公開

NSDockTilePlugInとは

NSDockTilePlugInとは、Mac appアプリケーションを起動していない間にもDock tile(Dockアイコンのこと)をカスタマイズできる方法です。例えばApple製のCalendar.appやClock.appのような動的なアイコン表示が可能です。3rdパーティではNovaやiA Presenterでも使われています。

https://developer.apple.com/documentation/appkit/nsdocktileplugin

Dock tile pluginの構造

アプリケーションバンドルの中に適切なプラグインバンドルを組み込むことで、Dockが別途ロードしてアプリケーション本体とは別のプロセスでDock tile pluginを走らせられます。例えばNova.appの中には.docktilepluginバンドルが組み込まれています。

プロジェクト設定

Dock tile pluginプロセスのTargetを用意

Xcodeで追加のTargetをBundleテンプレートで作ります。Bundle Extension(拡張子)には.docktilepluginが使われますが、.pluginでも機能するようです。

アプリケーション本体側のPlugInsにDock tile pluginを組み込む設定

アプリケーション本体のTargetのBuild Phasesペインで“+”ボタンを押して、New Copy Files Phaseでファイルコピーのフェーズを作ります。これを設定すると、プラグインをアプリケーションバンドル内のPlugInsに組み込むことができます。

  • DestinationをPlugIns and Foundation Extensionsを選択
  • 一覧にはDockTilePlugin.pluginを追加(この名前はBuild Settingsの設定次第)

アプリケーション本体側のInfo.plistにNSDockTilePlugInフィールドを追記

NSDockTilePlugInをキーとして、Dock tile pluginバンドルまでのパスを記述します。前回のCopy Files Phaseの設定ならば、ここはバンドル名のみで機能するはずです。

Dock tile pluginのPrincipalClassを設定

Dock tile plugin側のTargetのInfo.plistにNSPrincipalClassを設定します。今回はDockTilePluginという名前のクラス名にしましたが、命名は任意です。

Dock tile pluginのPrincipalClassを実装

PrincipalClassと同じ名前のクラスを実装しましょう。DockTilePlugin.swiftファイルを用意して、クラス名もそれにします。

import Cocoa

class DockTilePlugin: NSObject, NSDockTilePlugIn {

	func setDockTile(_ dockTile: NSDockTile?) {
		guard let dockTile else { return }
	
		let view = NSView()
		view.frame = NSRect(origin: .zero, size: dockTile.size)
		view.wantsLayer = true
		view.layer?.backgroundColor = NSColor.red.cgColor
		
		dockTile.contentView = view
		dockTile.display()
	}
	
	func dockMenu() -> NSMenu? {
		return NSMenu()
	}
}

setDockTile() はNSDockTilePlugInプロトコルで必須のメソッドです。この中でDockTileを更新する処理を実装します。

オプショナルでDock Menuを提供するdockMenu()も定義されています。

NSDockTileにはcontentViewがあり、ここにカスタムビューを設定することで任意のイメージを描画することができます。再描画処理は自動で行われないので、都度display()を実行する必要があります。

実装例はこのプロジェクトを参考にしてみてください。
https://github.com/rrroyal/AutomaticDockTile

Dock tileが更新されない場合はDockを再起動する

デバッグ最中などは古いDock tileがロードされたままになるので、都度killall Dockしましょう。

Mac App Storeに載せられない

NSDockTilePlugInを使ったアプリケーションはMac App Storeには載せられないようです。Info.plistにNSDockTilePlugInの記述があるだけで弾かれてしまうようです。

サンプルコード/関連コード

https://github.com/rrroyal/AutomaticDockTile
https://github.com/dagronf/DSFDockTile
https://github.com/CartBlanche/MacDockTileSample
https://github.com/HelmutJ/CocoaSampleCode

Discussion