project.pbxprojを弄ってXcodeにファイル追加を認識させる

#プロジェクト生成時

```
~/Documents/workspace_lab/DIFFER (master) % git status
On branch master
nothing to commit, working tree clean
```

とりあえず差分が無い状態にしておく

#ファイル追加時

まずSample.swiftというファイルをプロジェクトのルートに配置してみる。

```diff:DIFFER.xcodeproj/project.pbxproj(0~27行目付近）
// !$*UTF8*$!
{
	archiveVersion = 1;
	classes = {
	};
	objectVersion = 46;
	objects = {

/* Begin PBXBuildFile section */
		D72405291DFB285900502D3D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72405281DFB285900502D3D /* AppDelegate.swift */; };
		D724052B1DFB285900502D3D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D724052A1DFB285900502D3D /* ViewController.swift */; };
		D724052E1DFB285900502D3D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D724052C1DFB285900502D3D /* Main.storyboard */; };
		D72405301DFB285900502D3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D724052F1DFB285900502D3D /* Assets.xcassets */; };
		D72405331DFB285900502D3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D72405311DFB285900502D3D /* LaunchScreen.storyboard */; };
+		D724053B1DFB290200502D3D /* Sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = D724053A1DFB290200502D3D /* Sample.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
		D72405251DFB285900502D3D /* DIFFER.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DIFFER.app; sourceTree = BUILT_PRODUCTS_DIR; };
		D72405281DFB285900502D3D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
		D724052A1DFB285900502D3D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
		D724052D1DFB285900502D3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
		D724052F1DFB285900502D3D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
		D72405321DFB285900502D3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
		D72405341DFB285900502D3D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		D724053A1DFB290200502D3D /* Sample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sample.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
```

```diff:DIFFER.xcodeproj/project.pbxproj（40行目付近）
/* Begin PBXGroup section */
		D724051C1DFB285900502D3D = {
			isa = PBXGroup;
			children = (
				D72405271DFB285900502D3D /* DIFFER */,
				D72405261DFB285900502D3D /* Products */,
			);
			sourceTree = "<group>";
		};
		D72405261DFB285900502D3D /* Products */ = {
			isa = PBXGroup;
			children = (
				D72405251DFB285900502D3D /* DIFFER.app */,
			);
			name = Products;
			sourceTree = "<group>";
		};
		D72405271DFB285900502D3D /* DIFFER */ = {
			isa = PBXGroup;
			children = (
+				D724053A1DFB290200502D3D /* Sample.swift */,
				D72405281DFB285900502D3D /* AppDelegate.swift */,
				D724052A1DFB285900502D3D /* ViewController.swift */,
				D724052C1DFB285900502D3D /* Main.storyboard */,
				D724052F1DFB285900502D3D /* Assets.xcassets */,
				D72405311DFB285900502D3D /* LaunchScreen.storyboard */,
				D72405341DFB285900502D3D /* Info.plist */,
			);
			path = DIFFER;
			sourceTree = "<group>";
		};
/* End PBXGroup section */
```

```diff:DIFFER.xcodeproj/project.pbxproj（138行目付近）
/* Begin PBXSourcesBuildPhase section */
		D72405211DFB285900502D3D /* Sources */ = {
			isa = PBXSourcesBuildPhase;
			buildActionMask = 2147483647;
			files = (
				D724052B1DFB285900502D3D /* ViewController.swift in Sources */,
+				D724053B1DFB290200502D3D /* Sample.swift in Sources */,
				D72405291DFB285900502D3D /* AppDelegate.swift in Sources */,
			);
			runOnlyForDeploymentPostprocessing = 0;
		};
/* End PBXSourcesBuildPhase section */
```

以上４件の差分が出ました。

##PBXBuildFile Section
まず
/* Begin PBXBuildFile section */
の部分で発生した差分ですが、名前からビルドの対象ファイルに関する記述のように思えます。
この部分を消すと、TargetMemberShipが解除されるところからもビルドするファイル一覧が並んでいるようです。

##PBXFileReference Section
次に
/* Begin PBXFileReference section */
の部分の差分ですが、こちらは削除するとXcodeでの一覧から消えてしまいます。
名前からもファイルの参照を管理しているセクションのようです。

##PBXGroup Section
こちらはXcodeのディレクトリ階層の位置を指しています。
```
D724051C1DFB285900502D3D = {

}
```
がルート階層となっており、その中の要素はchildrenの中で定義されます。


##PBXSourcesBuildPhase Section
ここはXcodeのBuild PhasesのCompile Sourceの一覧のようです。

#Xcodeの処理を再現してファイルを追加する

project.pbxprojを直接編集してファイルを追加してみます。
Sample2.swiftというファイルをまずプロジェクト/プロジェクト名配下に配置します。

<img width="580" alt="スクリーンショット 2016-12-10 3.27.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/24979/3da6a475-afd5-bb63-421c-7dc7db8a31e5.png">

この時点では当然Xcodeはファイルを認識していません

<img width="285" alt="スクリーンショット 2016-12-10 3.27.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/24979/bf8daa6a-60f3-ab2c-7f4f-250784a645e6.png">

##PBXBuildFile Section
ここはビルドターゲットのファイルを管理する場所でした
Sample.swiftの追加時は以下のようになっていました。

```
D724053B1DFB290200502D3D /* Sample.swift in Sources */ = {isa = PBXBuildFile; fileRef = D724053A1DFB290200502D3D /* Sample.swift */; };
```

ユニークなキーに対してisa,fileRefという要素を渡しているようです。

```
SAMPLE2BUILDFILEREF = {
  isa = PBXBuildFile;
  fileRef = SAMPLE2FILEREF;
};
```
こんな感じでしょうか。

##PBXFileReference Section

```
D724053A1DFB290200502D3D /* Sample.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sample.swift; sourceTree = "<group>"; };
```

ここで注目すべきは`D724053A1DFB290200502D3D`の部分はPBXBuildFileでfileRefとして指定した値と同じということです。

```
SAMPLE2FILEREF = {
  isa = PBXFileReference;
  fileEncoding = 4;
  lastKnownFileType = sourcecode.swift;
  path = Sample2.swift;
  sourceTree = "<group>";
};
```
pathはプロジェクト名/プロジェクト名以下から始まっているのかな…？


##PBXGroup Section
ここではSample.swiftと同じ場所に置きたいのでchildrenの中に追加します。


```
children = (
				D72405281DFB285900502D3D /* AppDelegate.swift */,
				D724053A1DFB290200502D3D /* Sample.swift */,
				D724052A1DFB285900502D3D /* ViewController.swift */,
				D724052C1DFB285900502D3D /* Main.storyboard */,
				D724052F1DFB285900502D3D /* Assets.xcassets */,
				D72405311DFB285900502D3D /* LaunchScreen.storyboard */,
				D72405341DFB285900502D3D /* Info.plist */,
				SAMPLE2FILEREF,
			);
```

ここでもfileRefが使われてますね

##PBXSourcesBuildPhase Section
こちらはPBXBuildFileのキーを渡すようです。ビルドターゲットの中から選ぶような感じでしょうか

```
files = (
                D724052B1DFB285900502D3D /* ViewController.swift in Sources */,
                D724053B1DFB290200502D3D /* Sample.swift in Sources */,
                D72405291DFB285900502D3D /* AppDelegate.swift in Sources */,
                SAMPLE2BUILDFILEREF,
            );
```

##追記の結果

<img width="313" alt="スクリーンショット 2016-12-10 3.39.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/24979/b0b0fc15-54ab-23df-edf6-5e848a6239e0.png">

ちゃんとXcodeでも認識されました。

<img width="570" alt="スクリーンショット 2016-12-10 3.40.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/24979/e9cdb820-2b52-ff5b-e6a3-17becfa9c840.png">

特にfileRefやビルド管理のID名でパースしているような事は無さそうですね。