[Xcode][Android Studio]Project Templateの作成

# Xcode
## テンプレートの場所
環境によって多少異なりますが、

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

がデフォルトのテンプレート置き場となっています。

## ディレクトリ構成
Xcode Projectのテンプレートは継承できる構造になっており、テンプレートが細分化されています。
Single View App.xctemplateを例に説明します。

```
Single View App.xctemplate
 - Main.storyboard
 - TemplateIcon.png
 - TemplateIcon@2x.png
 - TemplateInfo.plist
```

### Main.storyboard
Storyboardの初期状態を指定できます。
Storyboardを使ったアプリのテンプレートを作成する場合はこのファイルを変更することで、プロジェクトを作成する度にViewやButtonを配置する手間が省けます。

### TemplateIcon.png
テンプレート選択画面のアイコンです。
サイズは48×48と2xの2種類あります。

### TemplateInfo.plist
プロジェクトを作成する際に実行する処理が書いてあります。
Xmlで書かれていますが、Xcodeで開くとProperty List形式で表示、編集できます。

## テンプレートの作成
テンプレートの作成は主にTemplateInfo.plistを編集して行います。

### 準備
雛形となるファイルは既存のものをコピーします。
どのディレクトリに作成するかでテンプレート選択画面での表示場所が変わります。
例えば、Templates/iOS以下にMyTemplateというディレクトリを作成し、Single View App.xctemplateをコピーしてMyTemplate.xctemplateを作成した場合、テンプレート選択画面はこのようになります。
<img width="745" alt="Screen Shot 2017-11-15 at 14.49.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/153433/e9c0d875-8bc0-59d1-a88d-4bed2f85c504.png">

### 各Keyの説明
#### Identifier
各テンプレートは、Identifierによりユニークになるように管理されています。
このIDが被ると、どちらかは反映されません。

#### Ancestors
継承するテンプレートを列挙します。
指定する場合はそのテンプレートのIdentifierを設定してください。

#### Concrete
この値がtrueになっているものがテンプレート選択画面で表示されます。
継承でしか使用しないテンプレートの場合はfalseにしておくのがよさそうです。

#### Description
テンプレートの説明を設定します。
どのバージョンからかは把握できていませんが、Xcode9ではテンプレート選択画面で表示されませんでした。
旧バージョンではテンプレート選択画面の下の方に表示されるようです。

#### SortOrder
テンプレート選択画面での表示順を設定します。

#### Options
テンプレート選択後の設定で出すオプションを設定します。
Single View Appの場合は選択した言語（Obj-CかSwift）によってView Controllerを作り分けています。

#### Definitions
プロジェクトの構成を設定します。
ディレクトリの作成やファイルの配置を行います。

`Groups`
プロジェクト内でのディレクトリを指定します。
要素を増やすと階層構造になります。

`Path`
実ファイルと関連付けます。
作成したテンプレートのディレクトリ（MyTemplate.xctemplate）のパスと一致させてください。

`SortOrder`
プロジェクト内での表示順序を設定します。

#### Nodes
初期状態ではないので追加してください。
実際に作成するファイルを設定します。
基本的にDefinitionsとセットで設定していきます。

#### Targets
初期状態ではないので追加してください。

`Frameworks`
Link Binary With Librariesから追加できるフレームワークを追加できます。
拡張子の.frameworkは除いて指定します。

`SharedSettings`
Build Settingの項目を設定します。
Xcodeでの表示と違う場合があるので設定の際は注意が必要です。

### Identifierの変更
Identifierに好きなIDを設定します。
Bundle IDのような逆ドメイン方式にするのがいいと思います。

```
<key>Identifier</key>
<string>org.masapp.MyTemplate</string>
```

### ViewControllerの配置
Single View Appの場合はデフォルトで選択した言語（Obj-CかSwift）によってView Controllerを作り分けています。
このようにplist内でコードも書けるので、ここに追記して作成することもできます。
ただ、この方法はかなり面倒なので、作成したテンプレートのディレクトリにファイルを用意してそれを配置する方が簡単です。
その場合、Optionsで作成している部分は不要なので削除してしまってください。

```
<key>Nodes</key>
<array>
    <string>ViewController.swift</string>
</array>
<key>Definitions</key>
<dict>
    <key>ViewController.swift</key>
    <dict>
        <key>Path</key>
        <string>ViewController.swift</string>
    </dict>
</dict>
```

### ファイルの配置
テンプレートのディレクトリに作成したファイルを配置し、NodesとDefinitionsの設定をしてプロジェクトの任意の位置に配置します。
このとき、プロジェクトのディレクトリ構造とテンプレートに配置したファイルの構造が違ってもちゃんとパスが指定してあれば問題ありません。

```
<key>Nodes</key>
<array>
    <string>Directory/SampleViewController.swift</string>
</array>
<key>Definitions</key>
<dict>
    <key>Directory/SampleViewController.swift</key>
    <key>Group</key>
    <array>
        <string>Directory</string>
    </array>
    <dict>
        <key>Path</key>
        <string>PathToTemplateDirectory/SampleViewController.swift</string>
    </dict>
</dict>
```

### Frameworkの追加
追加したいフレームワークをTargetsのFrameworksに設定します。
TargetsやFrameworksがない場合は追加してください。

```
<key>Targets</key>
<array>
    <dict>
        <key>Frameworks</key>
        <array>
            <string>WebKit</string>
        </array>
    </dict>
</array>
```

### Build Settingsの設定
TargetsのSharedSettingsに必要な項目を追加して設定します。
TargetsやSharedSettingsがない場合は追加してください。

#### Framework Search Pathsの設定
FRAMEWORK_SEARCH_PATHSを追加して設定します。

```
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>FRAMEWORK_SEARCH_PATHS</key>
            <array>
                <string>$(PROJECT_DIR)</string>
            </array>
        </dict>
    </dict>
</array>
```

#### Header Search Pathsの設定
HEADER_SEARCH_PATHSを追加して設定します。

```
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>HEADER_SEARCH_PATHS</key>
            <array>
                <string>$(PROJECT_DIR)</string>
            </array>
        </dict>
    </dict>
</array>
```

#### Library Search Pathsの設定
LIBRARY_SEARCH_PATHSを追加して設定します。

```
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>LIBRARY_SEARCH_PATHS</key>
            <array>
                <string>$(PROJECT_DIR)</string>
            </array>
        </dict>
    </dict>
</array>
```

#### Other Linker Flagsの設定
OTHER_LDFLAGSを追加して設定します。
Xcodeでの項目名と表記が違うので注意してください。

```
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>OTHER_LDFLAGS</key>
            <array>
                <string>$(PROJECT_DIR)</string>
            </array>
        </dict>
    </dict>
</array>
```

#### Runpath Search Pathsの設定
LD_RUNPATH_SEARCH_PATHSを追加して設定します。
Xcodeでの項目名と表記が違うので注意してください。

```
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>LD_RUNPATH_SEARCH_PATHS</key>
            <array>
                <string>$(PROJECT_DIR)</string>
            </array>
        </dict>
    </dict>
</array>
```

### Bridging-Headerの追加
ファイルの配置と同様にテンプレートのディレクトリに作成したBridgingHeaderファイルを配置し、NodesとDefinitionsの設定をしてプロジェクトの任意の位置に配置します。
TargetsのSharedSettingsにSWIFT_OBJC_BRIDGING_HEADERを追加してBridgingHeaderファイルへのパスを指定します。

```
<key>Nodes</key>
<array>
    <string>Template-Bridging-Header.h</string>
</array>
<key>Definitions</key>
<dict>
    <key>Template-Bridging-Header.h</key>
    <dict>
        <key>Path</key>
        <string>Template-Bridging-Header.h</string>
    </dict>
</dict>
<key>Targets</key>
<array>
    <dict>
        <key>SharedSettings</key>
        <dict>
            <key>SWIFT_OBJC_BRIDGING_HEADER</key>
            <string>${PROJECT_NAME}/Template-Bridging-Header.h</string>
        </dict>
    </dict>
</array>
```

# Android Studio
## テンプレートの場所
環境によって異なりますが、

```
/Applications/Android Studio.app/Contents/plugins/android/lib/templates
```

がデフォルトのテンプレート置き場となっています。

## ディレクトリ構成
新規プロジェクト作成時に必ず選択するactivitiesのうち、EmptyActivityを例に説明します。

```
EmptyActivity
 - globals.xml.ftl
 - recipe.xml.ftl
 - root
    - src
        - app_package
            - SimpleActivity.java.ftl
 - template_blank_activity.png
 - template.xml 
```

### globals.xml.ftl
定数を定義するファイルです。
定数化したいものがあればこのファイルに追記します。

### recipe.xml.ftl
プロジェクトを作成する際に実行する処理が書いてあります。
このファイルに追記してテンプレートを作成していきます。

### root
プロジェクト作成時に配置するファイルをこのディレクトリ以下に配置します。
このディレクトリ以下じゃないと絶対にダメということはありませんが、管理しやすいのでこちらにまとめるのがよさそうです。

### template_blank_activity.png
テンプレート選択画面の画像です。
サイズは512×512です。

### template.xml
テンプレート名や説明等、テンプレートの基本情報が書いてあります。
テンプレート選択後の設定項目の追加、削除もこのファイルで行います。

## テンプレートの作成
テンプレートの作成は、
・globals.xml.ftlで定数の定義
・template.xmlでテンプレートの基本情報の定義
・recipe.xml.ftlでプロジェクト作成時の処理を定義
して行います。

### 準備
雛形となるファイルは既存のものをコピーします。
今回はEmptyActivityをコピーしたものを使用して説明します。

### globals.xml.ftl
globals.xml.ftlに追記することで定数として参照できるようになります。
`<#inclide "path"/>`で別ファイルの定数を参照することもできます。

```
<?xml version="1.0"?>
<globals>
    <global id="appOut" value="./app" />
    <#include "../common/common_globals.xml.ftl" />
</globals>
```

### template.xml
#### テンプレート名と説明の変更
templateタグにあるnameプロパティを変更します。
Android Studioではこのnameで判断しているようで、他のテンプレートと同じ名前だと選択画面に表示されません。
descriptionを変更することで、説明を編集できます。

```
<template
    name="MyTemplataActivity"
    description="Creates a new template activity">
```

#### 入力項目の追加、削除
プロジェクト作成画面で入力する項目はparameterで定義されています。
作成するテンプレートに合わせて追加、削除してください。

`id`
項目の識別子です。
変数としてこのidで指定した文字列で参照できます。

`name`
入力項目のラベル名を設定します。

`type`
入力項目のタイプを設定します。
例えばチェックボックスにしたい場合はbooleanにします。

`default`
初期状態を設定します。
stringの場合だとここに設定した文字列が入力された状態で表示されます。

`help`
入力項目の説明を設定します。
入力画面の下の方に表示されます。

```
<parameter
    id="testParam"
    name="Test param"
    type="string"
    default="test parameter"
    help="This is test parameter." />
```

#### その他の項目の設定
`thumbs`
テンプレート選択画面で表示する画像を設定します。

`globals`
どのglobals.xml.ftlを参照するかを設定します。

`execute`
どのrecipe.xml.ftlを参照するかを設定します。

```
<thumbs>
    <thumb>template_blank_activity.png</thumb>
</thumbs>

<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
```

### recipe.xml.ftl
`mkdir`
ディレクトリを作成できます。
作成先のパスをatで指定してください。

```
<mkdir at="${escapeXmlAttribute(srcOut)}/directory" />
```

`instantiate`
ファイルを作成します。
fromには元となるテンプレートディレクトリに設置したファイルのパスを指定します。
toには作成先のパスを指定します。
template.xmlで設定したパラメータを参照したい場合は`${id}`で行えます。

```
<instantiate from="root/src/app_package/SimpleActivity.kt.ftl"
               to="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />
```

`open`
プロジェクト作成後に開いておくファイルを設定します。

```
<open file="${escapeXmlAttribute(srcOut)}/${activityClass}.kt" />
```

`copy`
ファイルをコピーします。
fromには元となるテンプレートディレクトリに設置したファイルのパスを指定します。
toにはコピーのパスを指定します。
template.xmlで設定したパラメータを参照したい場合は`${id}`で行えます。
ファイル内に`${ }`でパラメータを参照している場合はinstantiateで作成してください。

```
<copy from="root/build.gradle.ftl"
        to="${escapeXmlAttribute(appOut)}/build.gradle" />
```

`merge`
2つのファイルをマージします。
fromには元となるテンプレートディレクトリに設置したファイルのパスを指定します。
toにはマージ先のパスを指定します。

```
<merge from="root/AndroidManifest.xml.ftl"
         to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
```