Facebookアプリ申請文書にあったiOSシミュレータービルドで微妙にハマってた。

「Facebookのレビュー申請文書に、iOSシミュレータービルドっていうのがあるよ」と言われて『ほぇー！（°▽°』と思って試してみたら微妙にハマったので、メモ

実際に、該当する文章は以下

 * https://developers.facebook.com/docs/apps/review#completeform

>iOS Simulator Build or Apple Store ID listed in Settings

Facebookのレビュー全体の日本語訳はこの辺りがよさそう

* [Facebookのレビュー申請文書を翻訳してみた](http://qiita.com/ogawatti/items/e34f62504b15f62b98fe)

# iOSシミュレータービルドとは？
* ザックリというと、開発しているアプリを他のマシンのiOS Simulatorで動かすためのビルド（多分）
* Facebookへのアプリ申請とかだと、AppStoreでの公開前にFacebookの審査を受けたいはずなので、使えると便利なはず

# 手順
基本的にはFacebookの開発者向けサイトに記載されている

* https://developers.facebook.com/docs/ios/creating-ios-simulator-build-for-review#generate-simulator

## 実際に行った手順

### 1. 開発しているプロジェクトの xcodeprojファイルがあるフォルダに行く

```bash
$ cd MyApp
```

### 2. 最新のsdkのバージョンを確認する

* xcodebuild -showsdks

```bash
$ xcodebuild -showsdks
OS X SDKs:
	OS X 10.9                     	-sdk macosx10.9
	OS X 10.10                    	-sdk macosx10.10

iOS SDKs:
	iOS 8.1                       	-sdk iphoneos8.1

iOS Simulator SDKs:
	Simulator - iOS 7.0           	-sdk iphonesimulator7.0
	Simulator - iOS 7.1           	-sdk iphonesimulator7.1
	Simulator - iOS 8.1           	-sdk iphonesimulator8.1　←今回はコレ
```
 * 一番新しい iphonesimulatorを覚えておく

### 3. ビルドする

* xcodebuild -arch i386 -sdk iphonesimulator{version}

```bash
$ xcodebuild -arch i386 -sdk iphonesimulator8.1
（略）
** BUILD FAILED **
MyApp

The following build commands failed:
	CompileC build/MyApp.build/Release-iphonesimulator/MyApp.build/Objects-normal/i386/hoge.o MyApp/Controller/hoge.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
```
* ターゲットに入れていなかった何かがひっかかったようです
* 問題が無い場合は、ここで、BUILD SUCCEEDEDと出ているはずです

#### BUILD FAILEDした場合
* どういうスキーマとターゲットがあるのかを確認しておきます

```bash
xcodebuild -list
```
* Build ConfigurationsとSchemesで使うヤツを覚えておきます

* 『xcodebuild -schema {myscheme} -configuration {target configuration} -arch i386 -sdk iphonesimulator{version}』を実行

```bash
$ xcodebuild -scheme MyApp -configuration Release -arch i386 -sdk iphonesimulator8.1

(略）
    /usr/bin/touch -c /Users/ionis_h/Library/Developer/Xcode/DerivedData/MyApp-abcdefabcdefabcdefabcdefabcd/Build/Products/Release-iphonesimulator/MyApp.app

** BUILD SUCCEEDED **
```
 * BUILD SUCCEEDEDの直前にあるパスを記憶しておきます
  * "/Users/ionis_h/Library/Developer/Xcode/DerivedData/MyApp-abcdefabcdefabcdefabcdefabcd/Build/Products/Release-iphonesimulator/MyApp.app" の部分

##### 2015/12/9 追記
masuharaさんに教えて頂きました！
利用しているもの等の違いで、プロジェクトによっては、以下のコマンドになるようですよ。

```bash
$ xcodebuild -arch x86_64 -sdk iphonesimulator9.1 -configuration Release -workspace アプリ名.xcworkspace -scheme アプリ名
```
詳しくは[masuharaさんのコメント](http://qiita.com/ionis_h/items/6603fd3365188b7ee0de#comment-86cffd6e33f690222fd7)を参照してみてください。

### 4. 動作確認

#### I. マシン上のデバイス確認

```bash
$ xcrun simctl list devices

(略）
    iPhone 6 (********-****-****-****-************) (Booted)
```
* 表示されるデバイスIDを覚えておく
* Bootedと表記されているので、この場合はすでに起動済み

#### II. シミュレーター起動
1つ前の手順ですでに起動している場合は、この作業は不要

```bash
$ open -a "iOS Simulator" --args -CurrentDeviceUDID ********-****-****-****-************
```
* ***...の部分は先程覚えておいたデバイスID

##### CUI起動で良い場合
* 手動での動作確認が不要である場合は、GUIは不要なので、以下で

```bash
$ xcrun simctl boot
```

#### III. インストール
ビルド時に覚えておいたパスを使ってインストールする

```bash
$ xcrun simctl install booted /Users/ionis_h/Library/Developer/Xcode/DerivedData/MyApp-abcdefabcdefabcdefabcdefabcd/Build/Products/Release-iphonesimulator/MyApp.app
```

* 実はビルド時に、プロジェクト配下の「build/Release-iphonesimulator/」にもappフォルダが作成されている
 * ただし、こちらを指定すると以下のようなエラーが出てしまいインストールが出来なかった

```bash
$ xcrun simctl install booted build/Release-iphonesimulator/MyApp.app
simctl[10713:1007] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(
	0   CoreFoundation                      0x00007fff8ac2b25c __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00007fff95329e75 objc_exception_throw + 43
	2   CoreFoundation                      0x00007fff8ab2add1 -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 385
	3   CoreFoundation                      0x00007fff8ab40ad9 +[NSDictionary dictionaryWithObjects:forKeys:count:] + 57
	4   simctl                              0x00000001079f16a6 simctl + 13990
	5   simctl                              0x00000001079f2d5d simctl + 19805
	6   libdyld.dylib                       0x00007fff943c95fd start + 1
	7   ???                                 0x0000000000000004 0x0 + 4
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Abort trap: 6
```

なおインストール時に指定した、bootedは、起動させたデバイスIDを指定するのでもOKです。

#### IIII. 後始末
動作確認が終了したら、シミュレーターをシャットダウンする

```bash
xcrun simctl shutdown ********-****-****-****-************
```

* ***...の部分は覚えておいたデバイスID

その後は、シミュレーターにインストールした方のappをzipで固めて、facebookへ申請したりする。
このappファイルを他のマシンにコピーして、「4. 動作確認」以降の手順を行えば、開発マシン以外でsimulatorでの動作確認も出来るはず。
（そんな事がしたい状況はあまり無い気はします。）

# 参考にしたリンク
* [simctlでiOSシミュレータを制御する](http://qiita.com/garsue/items/aad6e11091b2331c6ce3)
* [Installing a WatchKit App via simctl](http://stackoverflow.com/questions/28597316/installing-a-watchkit-app-via-simctl)
* [How to Install the Roambi Simulator Build (Xcode 6)](https://support.roambi.com/hc/en-us/articles/203191640-How-to-Install-the-Roambi-Simulator-Build-Xcode-6-)
* [Xcode 6 - Launch simulator from command line](http://stackoverflow.com/questions/26031601/xcode-6-launch-simulator-from-command-line)