[AppKit] 選択できる NSSavePanel の作り方

複数の保存フォーマットをサポートする NSSavePanel の作り方を説明します

環境&対象

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

  • macOS Big Sur 11.2
  • Xcode 12.4

概要

AppKit が提供する NSSavePanel は、そのままでも フォルダ作成等の機能が使えますが、複数フォーマットをサポートしようとすると追加実装が必要になります。

Apple のドキュメントは、こちら

具体的には以下の点について 不足を感じると思います。

  • 保存フォーマットの選択
  • 保存ファイル名へのファイル拡張子の設定

NSSavePanel で上記の対応を行うための追加実装を説明します。

保存フォーマットの選択

デフォルトの NSSavePanel には、保存フォーマットを選択するような機能はついていません。
ユーザーの入力したファイル名の拡張子から判断するという手もありますが、あまりスマートではありません。

NSSavePanel に 保存フォーマットを選択できるようなプルダウンメニューを追加するのが一般的です。

accessoryView

NSSavePanel の accessoryView に ビューを設定すると 以下の場所に追加でビューを表示させることができます。

AccessoryViewLocation
AccessoryViewLocation

このアクセサリビューを使って、フォーマット選択を行えるようにします。

accessoryView の実装

画像を保存するという設定で、JPG ファイル/ PNG ファイルを選択できるようにしてみます。

NSSavePanel#accessoryView

上記アプリを起動すると以下のような動作になります。

保存ファイル名へのファイル拡張子の設定

NSSavePanel を開いたときに、保存ファイル名を設定しておくことができます。表示された後に、ユーザーが自分で変更することもできますが、ある程度自動で設定してくれると便利です。

複数フォーマットを選択できるようにしているときには、フォーマットに応じた拡張子を自動でつけてくれると便利です。

保存ファイル名の設定

NSSavePanel の nameFieldStringValue を設定することで、NSSavePanel が開かれたときに入力されている値を設定することができます。

先の例では、nameFieldStringValue に設定している “FileNameBase” という値と、allowedFileTypes で最初に設定されている jpg が組み合わされて、”FileNameBase.jpg” という値が表示されています。

選択されたフォーマットの検知

ユーザーが保存ファイルフォーマットを変更したことは、NSPopupButton の Target/Action を通じて取得することができます。

Target/Action を用いて、以下のような形になります。

NSPopUpButton に target/action 設定(1)

上記コードで何を選択されたかという情報を取得することはできるのですが、それを NSSavePanel に反映しようとすると問題が発生します。

具体的には、nameFieldStringValue を更新しても、すでに開かれている NSSavePanel で表示されているファイル名は、更新されません。

選択されたフォーマットのファイル名への反映

allowedFileTypes をうまく使うことで、保存ファイル名の拡張子をアップデートすることができました。

allowedFileType を更新すると NSSavePanel は更新されます
allowedFileType を変更すると、表示されているファイル名の拡張子も更新されるようです。
”ようです”と書いているのはこの辺りの動作についてはドキュメントには記載されておらず、実際の動作から推測しているためです。

先ほどの target/action で呼ばれる関数を以下のようにすると期待の動作になります。

NSPopUpButton に target/action 設定(2)

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

全コード

NSSavePanel example

まとめ:NSSavePanel でフォーマット選択できるようにする拡張

NSSavePanel の拡張
  • accessoryView を使うと、追加 UI を表示できる
  • allowedFileTypes を使うと、表示されているファイル名の拡張子も更新される

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

コメントを残す

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