[Xcode7]Project Templateを自作したので作り方をざっとまとめる

Xcodeでアプリを作る際，プロジェクトの構成は自分やチームで大体決まっていると思います．
私は以下のような構成でいつも開発を行っていますが，毎回同じ構成を作るのは面倒です．

```
- Project
  - project_name
    - Classes
      - Config
      - Utility
      - Model
        - Entity
      - View
      - Controller
      - Layout
    - Resources
      - Font
      - Assets.xcassets
```

そこで，色々参考にしながらプロジェクトテンプレートを自作することにしたので，まとめることにします．
参考にした記事はこちら↓

- http://d.hatena.ne.jp/kimuraw/20120905/p1
- http://ashplanning.blogspot.jp/2015/02/xcode-6.html
- http://www.telerik.com/blogs/how-to-create-custom-project-templates-in-xcode-7


# 準備
雛形となるファイルは既存のものをコピーします．
デフォルトのテンプレート置き場(環境によっては多少異なります．)である

```
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project\ Templates/
```

から，`Single View Application`と関連するファイルのテンプレートを使用します．
ターミナルで以下を実行します．

```bash

$ cd ~/Library/Developer/Xcode/Templates/Project\ Templates
$ mkdir MyTemplate
$ cd MyTemplate/
$ cp -R /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/Project\ Templates/iOS/Application/{Cocoa\ Touch\ Application\ Base.xctemplate,Storyboard\ Application.xctemplate,Single\ View\ Application.xctemplate} .
```

コピーした`Single View Application`のフォルダ名を好きな名前に変えます．

```bash

$ mv Single\ View\ Application.xctemplate MyTemplate\ Application.xctemplate/
```

準備はこれで終わりです．
Xcodeを開き，プロジェクトを新規作成すると，以下のようになっていることがわかると思います．

<img src="https://qiita-image-store.s3.amazonaws.com/0/93219/458a4bb6-4b7d-a2a2-3007-a3dd15949434.png" width=400>


# フォルダ構成
Xcode Projectのテンプレートは，継承できる構造になっており，テンプレートが細分化されています．
全て説明すると非常に長くなると思うので，今回使用するものだけ説明していきます．

まずは`MyTemplateApplication.xctemplate`から．
このフォルダは一番下の階層のテンプレートで，プロジェクト新規作成時にテンプレートとして現れるものです．
`Single View`や`Master-Detail`なんかですね．

```
- MyTemplate Application.xctemplate
  - Main.storyboard
  - TemplateIcon.tiff
  - TemplateInfo.plist
```

・Main.storyboard
　Storyboardの初期状態を指定できます．
　例えば，`TabBarController`をよく使うという人はこのファイルに
　配置しておけばプロジェクト立上げ時の手間を少し省けますね．

・TemplateIcon.tiff
　テンプレート選択画面のアイコンです．
　イラレなどで，テンプレートにあったアイコンにするといいと思います．

・TemplateInfo.plist
　ファイル構成やファイルの中身の記述ができます．
　今回はこのファイルをメインに弄っていきます．

　

```
- Storyboard Application.xctemplate
  - TemplateInfo.plist
```
次に`Storyboard Application.xctemplate`ですが，こちらは`Info.plist`周りの
Stroyboardの基本設定をするテンプレートになっています．
メインStoryboardのファイル名なんかを設定します．
`MyTemplate Application.xctemplate`の一つ上の階層のテンプレートです．

　

```
- Cocoa Touch Application Base.xctemplate
  - TemplateInfo.plist
  - LaunchScreen.storyboard
  - Images-iPad.xcassets
  - Images-iPhone.xcassets
  - Images-Universal.xcassets
```

その更に上の階層にある`Cocoa Touch Application Base.xctemplate`は，
Assetsの初期化ファイルやLaunchScreenの初期化ファイルの設定を行っているものです．


大体の役割がわかったところで，実際に中身を弄っていきます．

# テンプレートの基本情報の変更
各テンプレートは，固有のIDにより管理されています．
このIDが被ると，どちらかは反映されません．
(現に今Xcodeを見てみると，`SingleViewApplication`テンプレートが消えてしまっています．)
なのでまずは，IDを決めるところから入ります．

`MyTemplate Application.xctemplate`の中の`TemplateInfo.plist`を開いてください．
(見やすさの観点から，Xcodeで開いて説明していきます．)

　
![基本情報設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/04a17548-ad86-6a2a-9384-718c19276df9.png)

こんな感じの画面が出てくると思います．
この中のIdentifierに適当な文字列を記述してください．
Bundle IDのような逆ドメイン方式がいいかと思われます．

大まかに弄るであろう他の部分の説明をしておきます．

・Ancestors
　継承するテンプレートのIDを列挙します．

・Concrete
　この値が「YES」になっているものが，Xcodeのテンプレート選択画面で実際に現れるテンプレートになります．

・Description
　テンプレートの説明を記述できます．
　テンプレート選択画面の下の方に記載される内容です．

・SortOrder
　感じでわかると思いますが，テンプレートの表示順序を指定できます．

・Options
　テンプレート選択後の画面に出すオプションの設定です．(後述)

・Definitions
　ファイル内容や，別ファイルへの参照などを記述します．(後述)

・Nodes
　初期状態ではありませんが，実際に生成するファイルや内容を定義します．(後述)
　Definitionsと一緒に使っていくのが普通かと思われます．

　
`Storyboard Application.xctemplate`，`Cocoa Touch Application Base.xctemplate`も同様に，IDを書き直してください．

そして，`MyTemplate Application.xctemplate`は`Storyboard Application.xctemplate`を，
`Storyboard Application.xctemplate`は`Cocoa Touch Application Base.xctemplate`を継承しているので，
各ファイルの`Ancestors`も書き換えるようにしてください．
`com.apple.dt.unit.coreDataCocoaTouchApplication`は今回使わない(&設定箇所が増える)ので，今回は消してください．


# フォルダの構成を記述
今回は，以下のような構成にしていこうと思います．

```
- Project
  - project_name
    + AppDelegate.swift
    + Info.plist
    - Classes
      - Config
      - Utility
      - Model
        - Entity
      - View
      - Controller
        + ViewController.swift
      - Layout
    - Resources
      - Font
      + Assets.xcassets
```

まずは，`MyTemplate Application.xctemplate/`下に，構成したいものと同じものを作ります．

```
- MyTemplate
  - Main.storyboard
  - TemplateIcon.tiff
  - TemplateInfo.plist
  - Classes
    - Config
    - Utility
    - Model
      - Entity
    - View
    - Controller
    - Layout
  - Resources
    - Font
```

こんな具合に作れたら，`MyTemplate Application.xctemplate/TemplateInfo.plist`を弄っていきます．
`Nodes`には実際のファイル構成を，`Definisions`にはプロジェクトの構成を記述していきます．


![Classes追加.png](https://qiita-image-store.s3.amazonaws.com/0/93219/0a9c6100-fd64-a2e9-7026-e506d6af4794.png)


フォルダ構成だけなら，ぶっちゃけこれだけでいけます．笑
ですが，中にファイルを入れたりとなると，(後ろで少し触れますが，)困ることになるので，
以下のように**一番下の階層だけを記述**していきます．

![フォルダ構成追加.png](https://qiita-image-store.s3.amazonaws.com/0/93219/d4f48e3d-e244-a3fd-b28d-fbaa85661890.png)

プロジェクトを作成してもらえるとわかりますが，この段階まででは，記述したものがフォルダと認識されません．
`Definisions`のそれぞれの中身を記述していきましょう．

![group指定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/06c78b44-2f4a-ce74-aa7b-3a8a6ec1e8bd.png)

・Groups
　プロジェクト内でのフォルダを指定します．
　要素を増やすと階層構造になります．

・Path
　フォルダであることを認識させるために，実ファイルと関連付けます．
　先ほど作った`MyTemplate Application.xctemplate/`フォルダ内のフォルダと一致させてください．

・SortOrder
　フォルダの表示順序の指定です．
　数字が大きいほど上の方に表示されます．

　
ここまで設定できたらプロジェクトを作ってみてください．

<img src="https://qiita-image-store.s3.amazonaws.com/0/93219/991ea6ba-4666-514c-8b18-a15507e3cb38.png" width=200>&emsp;&emsp;&emsp;&emsp;&emsp;<img src="https://qiita-image-store.s3.amazonaws.com/0/93219/888e7b1c-f8cb-6c93-c892-faab26a4ae91.png" width=200>


プロジェクト，実フォルダとも，ちゃんと構築されていることが確認できます．

# ファイルを配置する
さて，続いては，ファイルを配置していきます．

デフォルトであるファイルは
- AppDelegate.swift
- Info.plist
- Main.storyboard
- LaunchScreen.storyboard
- ViewController.swift
- Assets.xcassets
となっているので，まずはこれらのファイルを配置していきます．
(AppDelegateとplistは，最上階層のテンプレートも弄らないといけなくなるので，今回はスルーします．)

## Storyboardの配置
まずは，`Main.storyboard`から配置します．

`Main.storyboard`の`Nodes`は，`Storyboard Application.xctemplate`に記述されているので，こちらを開いてください．
`Nodes`の`Base.lproj/Main.storyboard`となっている部分を，`Classes/Layout/Main.storyboard`としてください．

![Nodesの設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/c1f0b128-3023-4ee9-7a44-24470eb19885.png)

この設定で，`Main.storyboard`のファイルは`Classes/Layout`下に配置されます．
続いてプロジェクト内の配置を行うために，`MyTemplate Application.xctemplate/TemplateInfo.plist`に設定を書きます．
フォルダの時と同様に`Group`や`Path`を書きなおします．

![storyboard設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/6425cc10-8563-4e07-b830-cbddc60fa2c4.png)

こんな感じになりますね．

`LaunchScreen.storyboard`も同様に書き直してください．
`LaunchScreen.storyboard`は`Cocoa Touch Application Base.xctemplate/TemplateInfo.plist`内で両方設定できるかと思います．

![launch設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/31a0efcc-c9f3-445a-8c77-2dfe472c007c.png)

## ViewControllerの配置
次に，`ViewController.swift`の配置をしていきます．
`MyTemplate Application.xctemplate/TemplateInfo.plist`の`Options`を見てみると，それっぽい記述が見れます．

![options.png](https://qiita-image-store.s3.amazonaws.com/0/93219/630689f0-388e-2415-01ea-c49ce26a51e5.png)

これは，`languageChoice`というオプションの値(Swift, Obj-C)によってファイルを書き換えていることを示しています．
`languageChoice`は，プロジェクト名とか決めるときに選択するやつです．(ドロップダウンのやつ.）

このように.plist上でコードもかけますが，正直面倒くさいです．笑
パラメータの種類とかもよくわかっていません．笑
なので，テンプレートファイルを作ったほうが早い気がします．

```swift:ViewController.swift

//
//  ViewController.swift
//
//  Copyright © 2016年 Krimpedance. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}
```

こんな感じのファイルを作り，`MyTemplate Application.xctemplate/`下に置いて，設定を書けばちゃんと追加されます．

![VC設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/b2ab7489-afee-915f-98e5-145e01b45d00.png)


## Assets.xcassetsの配置
このファイル(フォルダ？)は，iPhone, iPad, Universalで中身が変わってきます．
`Cocoa Touch Application Base.xctemplate`を見て貰えばわかりますが，それぞれ別のものが用意されています．

これも，先ほどのViewControllerと同様，`Options`の`universalDeviceFamily`のところで分岐させてあります．
これまでと同様に適切に設定を書き換えてあげます．

![assets設定.png](https://qiita-image-store.s3.amazonaws.com/0/93219/c4a810ee-28f1-4101-1a3d-f0ed51616a8f.png)

載せてはいませんが，`Nodes`の方も忘れずに変えてください．


## 動作チェック
以上で一通りのテンプレートの作成は終了です．
新規プロジェクトを作成し，確認してみてください．

## サンプル
https://github.com/krimpedance/MyTemplate

# 終わりに
今回は，普段の繰り返し作業を軽減するための一環としてプロジェクトテンプレートを作成してみました．
まだ細かい所の理解度が足りないですが，わりかし楽しかったです．
そのうちファイルテンプレートも作ってみますo(｀ω´ )o