Swiftを使ったMac OS Xアプリの開発【Storyboard編】

**2018/3/13 Swift 4 対応**

Swiftに関する日本語の情報もかなり増えてきているように感じますが、殆どがiOSアプリ開発に関するものです。そこで、趣味でMac OS Xアプリ開発を行いましたので、数回に分けて記事にしていこうと思います。
ちなみに、Macの利用比率が世界的に低いため、利益などを考慮する場合は、WebアプリやJavaアプリとして開発したほうがいいかもしれません。また、Swiftで開発を行うと、昔のMac OSで対応できないものが出てくるようです。


## 前提条件
iOSアプリの開発歴があるものとして解説を行いますので、共通な作業は省略している箇所があります。
また、この記事は以下のアプリを開発するにあたって記述したものです。アプリに実装する機能などによっては、追加で必要なことや、今回の作業に不要なことが含まれている可能性があります。

>[KeiSignal](https://itunes.apple.com/jp/app/keisignal/id1144071713?mt=12)
>プロ生ちゃんが時間を知らせてくれるMac専用の時報アプリケーションです。
>ミュート機能など、複数の設定が可能。
>課金・広告などは一切ございません。

## 開発環境
Mac OS X 10.11.6
Xcode 7.3.1

## 完成作品
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/5a3d79fd-5745-b7ba-2e9a-0a5ca6f2e60e.png" alt="完成作品" title="完成作品" with="300" height="260" />
</div>

多くのアプリケーションに見られるWindowへのパーツ配置と、ステータスバーに表示されるメニューの作成を行います。（今回はあまりコード書きません）
ソースを[GitHub](https://github.com/AkkeyLab/MacOSAppTraining01)に置いていますので、よければご利用ください。

## 1.プロジェクト作成
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/dfd1dbf3-2238-6703-9d40-87e8f3521e31.png" alt="プロジェクト作成" title="プロジェクト作成" with="300" height="300" />
</div>

お馴染みのこの画面で、 **OS X** から **Cocoa Application** を選択します。  

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/d1aaed60-cf64-cfc4-89da-d24cd361218f.png" alt="プロジェクト作成" title="プロジェクト作成" with="300" height="300" />  
</div>  

最初に少し悩むのはココかもしれません。
以下を参考に設定した上で、Nextからプロジェクトの保存先を選択して保存してください。
1. iOS同様に入力してください
2. 今回は **Swift** を選択します
3. 開発手法や開発内容によって臨機応変に変更します（今回は **Use Storyboards** にcheck）

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/667feee3-8826-5d49-cc32-cdf9bfaa75a5.png" alt="プロジェクト作成" title="プロジェクト作成" with="300" height="300" />  
</div>

上の画像はStoryboardを開いたものですが、このようにプロジェクトが作成されます。Storyboard上には、起動時に表示されるWindowが1つあり、数多くのメニューが既に用意されています。これからアプリを作成していきますが、不必要なメニューは削除しても構いません。

## 2.ステータスバーメニューの作成
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/db65acff-095e-712a-c4fd-c2ad9e747ff3.png" alt="メニューの作成" title="メニューの作成" with="300" height="300" />
</div>

右のパーツ一覧がiOSよりも豊富で、いろいろ見てみたくなると思いますが、ちょっと我慢してください（笑）。
パーツの中に、 **Menu** というものがあります。これを、既にあるメニューオブジェクトの上部に追加します。（既にあるアイコンの上ではなく、隙間に入れ込む感じです）

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/cc7cc8ce-c0f0-5920-8b35-6ea00d920561.png" alt="メニューの作成" title="メニューの作成" with="300" height="300" />
</div>   

このように、ちっちゃいメニューが上部に表示されたら成功です。左側の一覧では、上の図のように対応しています。メニューにかぎらず、パーツの配置場所変更以外は左側の一覧で操作することをおすすめします。リンクを貼るだけのつもりが数ピクセル動いてしまったというトラブルを防ぐことが出来ます。

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/4932bcec-cf22-f8dc-3d1d-f5fb5bf959e8.png" alt="メニューの作成" title="メニューの作成" with="300" height="300" />
</div>

次に、メニューを増やしてみましょう。パーツ一覧にある **Menu Item** を利用します。ここらへんの操作はiOS同様です。

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/fd418e54-a6c2-af29-6905-77c9a111cf85.png" alt="メニューの作成" title="メニューの作成" with="300" height="300" />
</div>

メニューがジャンル分けされているアプリって見たことありませんか？（おそらく皆さん見たことあると思います）
Xcodeのメニューを見てもわかりますが、メニューの中に区切りの線があると思います。これは **Separator Menu Item** 利用することで実装できます。

## 3.Window Controllerとオートレイアウト
### 3.1.Window Controller
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/a7aa990c-0d66-be90-b57e-0daa6a6ea0e7.png" alt="Window Controller" title="Window Controller" with="300" height="300" />
</div>

iOS開発でお世話になっている **View Controller** など、様々なパーツがありますが、今回使うのは **Window Controller** です。上の画像のようになったら成功です。

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/3f809363-b998-2742-e800-616a53f3d5ac.png" alt="Window Controller" title="Window Controller" with="300" height="300" />
</div>

では、先ほど作成したメニューからWindowを呼び出せるようにしてみましょう。 **Menu Item** からcontrolを押しながら **Window Controller** に向けてドラッグしてつなぐだけです。これも、iOSアプリ開発と同じです。

### 3.2.オートレイアウト
iPhoneとは違ってWindowサイズを大幅に変えることが出来ます。そこで、注意すべきレイアウト方法を記述したいと思います。

#### 3.2.1.横幅を固定
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/67fa8e5f-c095-cb17-2ba2-0f8db938f4a8.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

お待たせしました！ここからは、好きなパーツをレイアウトしてみてください！パーツを配置するのはWindow ControllerではなくView Controllerの方なので注意してください。
複数の選択肢を選ぶ際に利用する **Pop Up Button** を使ってみます。
1. **Pop Up Button** を中央に配置
2. 高さと幅を固定  

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/d2a24147-4eeb-3fe1-c0bd-a6e6689cc978.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

3. 中央に来るように制約を追加  

このようにすると、いくらWindowを大きくしても、パーツは同じ大きさで中央に表示され続けます。

#### 3.2.2.横幅を可変
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/81ea1d09-fd37-c49b-f8bb-6a3485f06e0e.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

先ほどは、横幅まで固定してしまいましたが、今回は可変にしてみたいと思います。
1. **Pop Up Button** を中央に配置
2. 高さを固定
3. 左右の端との距離に関する制約をつける

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/c56e3a70-f0f1-b609-b5d3-4e8a964d8dba.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

4. 中央に来るように制約を追加

このようにすると、Windowを横に広げた時、パーツも同様に横に広がっていきます。

<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/aa1b0f88-b672-1e37-9e94-efa7a539b384.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

上記の2通りの制約を追加した場合の実行結果を示します。上のWindowが横幅を可変にしたもので、下のWindowが横幅を固定にしたものです。パーツの種類などに合わせて使い分けましょう。
GitHubに置いているsampleは、起動時に表示されるWindow上のパーツは横幅を固定に、メニューから表示させる方は横幅可変にしています。

### 3.3.おまけ
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/1ab27c41-1f16-1604-5285-e3493c8568e6.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

Window ControllerのWindowを選択すると、右側の設定欄でWindowのサイズと表示位置なども設定可能です（Window表示直後の初期値です）。ちなみに、WindowのタイトルはView Controllerではなく、ココで設定する必要があります。

## 4.ステータスバーメニューを表示させる
<div align="center">
<img src="https://qiita-image-store.s3.amazonaws.com/0/128344/5446e367-b9e7-92d8-5b3f-1faea50a6420.png" alt="オートレイアウト" title="オートレイアウト" with="300" height="300" />
</div>

実は、ステータスバー上にアイコン又は文字を表示させ、そこからメニューを表示させるには、プログラムを多少書く必要があります（Storyboardだけでもできるのかな？）。プログラムは以下のとおりです。
> AppDelegate.swift  

~~~swift
import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

    // Storyboardからリンクさせる
    @IBOutlet weak var menu: NSMenu!
    // StatusBar上に表示させるItemのオブジェクトを生成
    var statusItem = NSStatusBar.system.statusItem(withLength: -1)

    func applicationDidFinishLaunching(aNotification: NSNotification) {
        // Insert code here to initialize your application

        // 今回は文字を表示させてみます
        statusItem.title = "Akkey"
        // お好みで設定を
        statusItem.highlightMode = true
        // Storyboardで作成したmenuを追加
        statusItem.menu = menu
    }

    func applicationWillTerminate(aNotification: NSNotification) {
        // Insert code here to tear down your application
    }

}
~~~

## 5.最後に
あとは、実行するだけです。エミュレータが起動することなく、Macで直接起動してくれます。
他にもMac OS Xアプリ開発に関する記事を書いていく予定です。もしよろしければご覧ください。
あと、アプリもダウンロードしてくれると嬉しいです＼(^o^)／