ウインドウを閉じたときに終了させる | macOSアプリの作り方

Cocoa版Hello World作成の続きです。今回はウインドウを閉じたときにアプリを終了させる処理を追加します。

この記事では前回の記事で作成したCocoa版Hello Worldの続きから行います。前回の記事に沿って作成している場合はそれを使用してください。作成されていない場合は、前回の記事の末尾からサンプルコードをダウンロードしてご利用ください。

目次

デリゲートについて

AppKitは、AppKit側からアプリ側の処理を実行するために、デリゲートパターンを使用します。デリゲートという英単語は「委譲」や「代表者」などという意味がありますが、AppKitを使ったアプリ開発では処理の一部を代行することを意味します。コールバックオブジェクトやコールバック関数などをイメージしても良いと思います。

SwiftやObjective-Cでは、デリゲートはプロトコルで定義し、デリゲートオブジェクトはプロトコルが定義するメソッドを実装したプロトコルの適合クラスのインスタンスです。

言葉で定義しようとすると複雑になってしまいますが、使っていくと何となくイメージ出来るようになると思います。

NSWindowDelegate

AppKitではウインドウが閉じられると、ウインドウのデリゲートのメソッドを実行します。実行されるメソッドは、NSWindowDelegateプロトコルの次のメソッドです。

- (void)windowWillClose:(NSNotification *)notification;

デリゲートクラスを実装する

NSWindowDelegateプロトコルの適合クラスを実装します。Cocoa版Hello Worldはごく小規模なアプリなので、HelloWindowControllerクラスで実装して、HelloWindowControllerクラスがウインドウコントローラとデリゲートを兼任させます。ウインドウ関連の制御を一箇所にまとめた方が分かりやすいという理由もあります。

デリゲートのコードを追加する

次のように、HelloWindowController.swiftにコードを追加します。

import Cocoa

class HelloWindowController: NSWindowController, NSWindowDelegate {
    
    let minWindowWidth: CGFloat = 200
    let minWindowHeight: CGFloat = 150
    let maxWindowWidth: CGFloat = 1200
    let maxWindowHeight: CGFloat = 900

    override func windowDidLoad() {
        super.windowDidLoad()
        
        window?.minSize = CGSize(width: minWindowWidth,
                                 height: minWindowHeight)
        window?.maxSize = CGSize(width: maxWindowWidth,
                                 height: maxWindowHeight)

        window?.makeKeyAndOrderFront(nil)
        window?.center()        
    }

    func windowWillClose(_ notification: Notification) {
        NSApplication.shared.terminate(self)
    }
}

変更箇所は次の2箇所です。

  • NSWindowDelegateの宣言を追加
  • windowWillClose()メソッドを追加

アプリを終了させるには

AppKitでアプリを終了させるには、NSApplicationクラスのterminate()メソッドを使用します。NSApplicationクラスのsharedプロパティで共有インスタンスを取得できます。

sharedプロパティで取得できる共有インスタンスは、アプリのプロセス毎に1つインスタンスが作成され、アプリ内共通で使用します。

ウインドウにデリゲートを設定する

ウインドウにデリゲートを設定するには、Storyboardファイル内で設定する方法とコードで設定する方法があります。

コード設定する場合

コードで設定する場合は、NSWindowクラスのdelegateプロパティにインスタンスを設定します。

Storyboardファイルで設定する場合

Storyboardファイルで設定する場合は、次のように操作します。但し、Cocoa版Hello Worldの場合は、既にウインドウコントローラがデリゲートに設定されています。Xcodeのバージョンによっては異なるので、確認してみましょう。

次のように操作します。

(1) Main.storyboardを開きます。

(2) Window Controller SceneWindow ControllerWindowを選択します。

(3) Connectionインスペクタを開き、Outletsdelegateに設定されているオブジェクト確認します。

接続先のオブジェクトを確認する
接続先のオブジェクトを確認する

(4) 外れている場合やWindow Controller以外が設定されている場合は、次のスクリーンキャプチャを参考に、delegateWindow Controllerを接続してください。スクリーンキャプチャの(1)から(2)までドラッグ&ドロップして、(1)から伸びる青い線を接続します。

なお、Storyboard上で設定可能なdelegateなどのプロパティを「アウトレット」と呼びます。

Window Controllerをdelegateに接続する
Window Controllerをdelegateに接続する

テスト

アプリを実行してください。ウインドウが表示されたら、ウインドウのクローズボックスをクリックして閉じます。すると、アプリが終了します。「File」メニューから「Close」を選択して、メニューからウインドウを閉じた場合も終了します。

サンプルコードのダウンロード

今回の記事で作成したサンプルコードはこちらからダウンロードできます。

著書紹介

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Akira Hayashi (林 晃)のアバター Akira Hayashi (林 晃) Representative(代表), Software Engineer(ソフトウェアエンジニア)

アールケー開発代表。Appleプラットフォーム向けの開発を専門としているソフトウェアエンジニア。ソフトウェアの受託開発、技術書執筆、技術指導・セミナー講師。note, Medium, LinkedIn
-
Representative of RK Kaihatsu. Software Engineer Specializing in Development for the Apple Platform. Specializing in contract software development, technical writing, and serving as a tech workshop lecturer. note, Medium, LinkedIn

目次