SwiftによるStoryBoardでのmacOS向け環境設定ウインドウ表示方法

macOS向けのアプリケーション開発において、概ね作る必要があるものに、環境設定(Preferences)がある。
StoryBoard導入前までは、特に考えることもなくNSPanelを使えば良かったが、StoryBoard導入後は、環境設定ウインドウを表示させる方法がちょっと手間になった。(筆者だけか?)
macOS向けのアプリケーションもまた日々作られ続けている以上、環境設定の必要性も当然ある。にも関わらずググっても資料が少ないのは、開発者によるいじめではないかと勘ぐったりもするが、それは置いておく。
敢えて秘密にしておくべきことを暴露することになるのかは分からないが、自分の備忘録も兼ねて書くことにする。

初めに、このブログエントリで扱うことを明記しておく。このブログエントリでは、Swiftで、単純なタブなし環境設定を表示する手順を説明する。
理由は、Objective-Cによるタブあり環境設定については、こちらのページが詳しく、またSwiftで、タブあり環境設定ウインドウを作る方法については、こちらのページが詳しいためである。
両ページの谷間にあるウインドウの表示方法は、もしかすると常識なのかも知れないが、筆者は知らずに苦労をした。それがこのブログエントリを書く理由である。

  1. NSWindowのサブクラスの追加
    NSWindowを親クラスとするカスタムサブクラスPreferencesWindowを追加する。

    カスタムサブクラスの追加

    記述するコードは以下の通り。これはこちらのページのコードの一部をSwiftに変換したものだ。目的は当然同じで、エスケープキーで環境設定ウインドウを閉じることである。(キャンセルオペレーションの上書き:5-8)

                import Cocoa
    
                class PreferencesWindow: NSWindow {
    
                    override func cancelOperation(_ sender: Any?) {
    
                        self.close()
                    }
                }
            
  2. ウインドウコントローラーの追加
    StoryBoardを開き、環境設定に用いることになるウインドウコントローラーを一個追加する。

    追加したウインドウコントローラーはセグエによる接続は行わない。下図にある通り、StoryBoard IDとコントローラー名を設定すれば、Xcodeの警告は消える。

    ウインドウコントローラーの追加

  3. 上記のウインドウへのカスタムクラス指定
    下図のように、ウインドウコントローラーのウインドウのクラスをPreferencesWindowに指定する。

    ウインドウへのカスタムクラスの指定

  4. アクションを接続
    環境設定(メニュー項目)とAppDelegateをアクションで接続する。StoryBoardのApplication Sceneからアプリケーションメニューを開き、環境設定項目からAppDelegate.swiftにIBActionを接続する。アクションの名前は、筆者はshowPreferencesWindowとした。

  5. 環境設定ウインドウを開く/閉じるコードの追加
    AppDelegate.swiftを以下のように編集する。

                import Cocoa
    
                @NSApplicationMain
                class AppDelegate: NSObject, NSApplicationDelegate {
    
                    var preferencesWindowController : NSWindowController?
    
                    func applicationDidFinishLaunching(_ aNotification: Notification) {
                        // Insert code here to initialize your application
                    }
    
                    func applicationWillTerminate(_ aNotification: Notification) {
                        // Insert code here to tear down your application
                    }
    
                    @IBAction func showPreferencesWindow(sender: AnyObject) {
    
                        if (NSApplication.shared().mainWindow?.title == NSLocalizedString("Preferences",  comment:"Preferences")) {
    
                            NSApplication.shared().mainWindow?.close()
    
                        } else {
    
                            if (preferencesWindowController == nil) {
                                let storyboard = NSStoryboard(name: "Main", bundle: nil)
                                preferencesWindowController = storyboard.instantiateController(withIdentifier: "PrefsWindow") as? NSWindowController
                            }
    
                            if (preferencesWindowController != nil) { preferencesWindowController!.showWindow(sender) }
                        }
                    }
                }
    
            

    上記コードでは、

    1. Preferencesというタイトルのウインドウがメインウィンドウなら閉じる(18-22)
    2. Preferencesというタイトルのウインドウがない場合、(22)
      preferencesWindowControllerがnilならば、storyboardからインスタンスを作り、(24-27)
    3. それを表示する(29)

    という作業を行っている。

以上。

この投稿へのコメント

コメントはありません。

コメントを残す

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

この投稿へのトラックバック

トラックバックはありません。

トラックバック URL