Scala/JavaでiOSアプリを作るtipsその２

#概要
これまでxcodeとの連携を手作業で行っていたのですが、これを自動化しました。
プロジェクトのテンプレートはこちらです。
https://github.com/chototsu/mikumikustudio-gdx

今回追加したのはxcodebuildというタスクです。
このタスクを実行すると、xcode_iosというディレクトリにあるxcodeプロジェクトをコンパイルし、自動的にUniversal Static Libraryを作成します。また、xibファイルを解析し、そのJavaバインディングコードをios/generatedディレクトリに自動生成します。

#ライブラリ生成
今回作成したのはこのようなプロジェクトです。
![スクリーンショット 2014-02-23 21.32.19.png](https://qiita-image-store.s3.amazonaws.com/0/32280/7a0a4c62-8b20-185d-7bac-cfef02907fc4.png)

このプロジェクトの「lib」というターゲットがライブラリ用のターゲットです。ライブラリに含めたいクラスはこのターゲットに入れるようにして下さい。
尚、UIViewControllerのクラスはこのターゲットに含めないで下さい。UIViewControllerのクラスはRoboVM側で生成しますので、こちらに同名のクラスがあると名前が衝突してしまいます。

#画面生成
画面はUIViewControllerのサブクラスとして作ります。
![スクリーンショット 2014-02-23 21.37.35.png](https://qiita-image-store.s3.amazonaws.com/0/32280/490c56a1-2e91-c465-97fd-9ce28f8a426f.png)
この時、「With XIB for user interface」をチェックするようにして下さい。
繰り返しますが、ここで作ったクラスはlibターゲットに含めないで下さい。名前が重なって実行時にエラーが発生します。

クラスを作ったら普通に画面を作成し、OutletやActionを作成します。
![スクリーンショット 2014-02-23 21.39.19.png](https://qiita-image-store.s3.amazonaws.com/0/32280/92830122-7c89-f20a-e1d3-6b3427f33044.png)

作成出来たらsbtからxcodebuildを実行します。

```
$ sbt
> ios/xcodebuild
```

するとxibが自動的にnibにコンパイルされ、このようなクラスが生成されます。

```java
package view;
import org.robovm.cocoatouch.uikit.*;
import org.robovm.objc.Selector;
import org.robovm.objc.annotation.BindSelector;
import org.robovm.objc.annotation.CustomClass;
import org.robovm.objc.annotation.TypeEncoding;
import org.robovm.rt.bro.annotation.Callback;
@CustomClass("TestAppViewController")
public abstract class TestAppViewController extends UIViewController {
	public TestAppViewController() {
		super("TestAppViewController", null);
	}	protected UILabel label1;
	@SuppressWarnings("unused")
	@Callback
	@BindSelector("setLabel1:")
	@TypeEncoding("v@:@")
	private static void setLabel1(TestAppViewController self, Selector selector, UILabel label1) {
		self.label1=label1;
	}
	@SuppressWarnings("unused")
	@Callback
	@BindSelector("getLabel1")
	@TypeEncoding("v@:@")
	private static UILabel getLabel1(TestAppViewController self, Selector selector) {
		return self.label1;
	}
	@SuppressWarnings("unused")
	@Callback
	@BindSelector("buttonAction:")
	@TypeEncoding("v@:@")
	private static void buttonAction(TestAppViewController self, Selector selector, UIButton sender) {
		self.buttonAction(sender);
	}
	abstract protected void buttonAction(UIButton sender);
	@SuppressWarnings("unused")
	@Callback
	@BindSelector("button2Action:")
	@TypeEncoding("v@:@")
	private static void button2Action(TestAppViewController self, Selector selector, UIButton sender) {
		self.button2Action(sender);
	}
	abstract protected void button2Action(UIButton sender);
}
```

このクラスはabstractクラスですのでそのままでは使えません。
使うためにはこのクラスを継承したクラスを作成します。
これはScalaの例です。

```scala
class TestAppViewControllerImpl extends TestAppViewController {
  protected override def buttonAction(sender: UIButton): Unit = {
    label1.setText("Hello!!")
  }

  protected override def button2Action(sender: UIButton): Unit = {
    label1.setText("World!!")
  }
}
```

この画面を表示するためにはdidFinishLaunchingでaddSubviewしてやります。

```scala
  override def didFinishLaunching(application: UIApplication, launchOptions: NSDictionary[_ <: NSObject, _ <: NSObject]): Boolean = {
    super.didFinishLaunching(application, launchOptions)
    testAppViewController = new TestAppViewControllerImpl
    app.getUIViewController.getView.addSubview(testAppViewController.getView)
    true
  }
```


実行すると、作成した画面がOpenGLの画面の上に表示される事が確認出来ます。
作成したボタンを押すとlabelの内容が変化する事が分かります。
![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32280/5dd563bd-5466-caed-3707-35c44ae70e10.png)

##制限
現在はすべてのUIButtonのTouch Up Insideアクションにしか対応していません。
その他のアクションはサブクラス側に手作業で追加して下さい。

#TODO

*Objective Cのバインディグを自動生成したい（これはかなり大変そう・・・）。
*xibの全action, outletに対応する。
*maven centralリポジトリに作ったバインディグを登録する。

#終わりに
開発環境が整ってきて、だいぶ作業が捗るようになりました。
Javaのエコシステムを利用してiOSの開発が出来てしまうのは凄い事だと思います。
ちなみに私が公開したアプリ Tiny AR liteは
https://itunes.apple.com/jp/app/tiny-ar-lite/id806062401?mt=8
RoboVMの作者のNiklas Therning氏に世界初のScalaで書かれたiOSアプリとの公式認定を受けております（笑）
当初安定性の心配をしていたのですがユーザー様からの評価では概ね安定しているようで、ほっとしています。
RoboVMは十分安定していると言えるでしょう。