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 Scene
のWindow Controller
のWindow
を選択します。
(3) Connectionインスペクタを開き、Outlets
のdelegate
に設定されているオブジェクト確認します。
(4) 外れている場合やWindow Controller
以外が設定されている場合は、次のスクリーンキャプチャを参考に、delegate
にWindow Controller
を接続してください。スクリーンキャプチャの(1)から(2)までドラッグ&ドロップして、(1)から伸びる青い線を接続します。
なお、Storyboard上で設定可能なdelegate
などのプロパティを「アウトレット」と呼びます。
テスト
アプリを実行してください。ウインドウが表示されたら、ウインドウのクローズボックスをクリックして閉じます。すると、アプリが終了します。「File」メニューから「Close」を選択して、メニューからウインドウを閉じた場合も終了します。
サンプルコードのダウンロード
今回の記事で作成したサンプルコードはこちらからダウンロードできます。