Objective-C で開発されたアプリケーションの一部を RubyMotion 製のアプリに合体させる方法


RubyMotion で開発したコードを静的ファイルにコンパイルして Objective-C のプロジェクトで使用できるのは [RubyMotion でスタティックライブラリを作成し、 Xcode プロジェクトで利用する](http://watson1978.github.io/blog/2013/06/06/creating-rubymotion-static-library/) でご存知の方も多いと思います。

また、CocoaPods を使ったり [app.vendor_project](http://www.rubymotion.com/developer-center/guides/project-management/#_vendoring_3rd_party_libraries) を使うことで Objective-C で書かれたオブジェクトを RubyMotion 内で使用することが出来ることもご存知かと思います。

ということは、既存の Objective-C で開発されたアプリケーションの特定の機能、例えば Storyboard 上で Tab Controller を使ってつくられた、アプリケーションのとある 1 タブの中身をそのまま丸ごと RubyMotion で使用するなんてこともできるのでしょうか？

こんな変態なことも実はできるのです。やってみます。

## 1. プロジェクトの作成と合成

合成と言うと、ソシャゲっぽくて素敵ですね。

Objective-C 製のアプリは以下を用意しました。

![スクリーンショット 2013-12-22 20.55.07.png](https://qiita-image-store.s3.amazonaws.com/0/747/64535003-fb12-6f9c-9cd4-4b504dd96b55.png "スクリーンショット 2013-12-22 20.55.07.png")


Storyboard を使った、2タブの単純なアプリです。Storyboard 上の View Controller には Storyboard ID を振ってあります。

そのうち、左のタブの FirstViewController を使用してみましょう。RubyMotion で新しいプロジェクトをつくり、Xcode のプロジェクトを vendor/ 内にコピーします。

```
$ motion create HentaiMotion
$ cd HentaiMotion
$ mkdir vendor
$ cp -r /path/to/HentaiProject vendor/
```

こんな感じの構成になっているはずです。

```
$ tree -L 3
.
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── app
│   └── app_delegate.rb
├── build
├── resources
│   └── Default-568h@2x.png
├── spec
│   └── main_spec.rb
└── vendor
    └── HentaiProject
        ├── HentaiProject
        ├── HentaiProject.xcodeproj
        └── HentaiProjectTests
```

次に Xcode で vendor 内にコピーした HentaiProject.xcodeproj を開き以下のように操作します。

## 2. 合体用に静的ライブラリとしてコンパイルするように新しいターゲットをつくります。

![スクリーンショット 2013-12-22 21.21.44.png](https://qiita-image-store.s3.amazonaws.com/0/747/1997955f-43b1-a0d4-32a2-4f16f0e24ee9.png "スクリーンショット 2013-12-22 21.21.44.png")
![スクリーンショット 2013-12-22 21.22.48.png](https://qiita-image-store.s3.amazonaws.com/0/747/9a980ba8-a7e9-80dd-c2ea-d3d5b2fda045.png "スクリーンショット 2013-12-22 21.22.48.png")
![スクリーンショット 2013-12-22 21.23.00.png](https://qiita-image-store.s3.amazonaws.com/0/747/bb660cda-f1ce-067e-0a1b-0ee1c7462c2d.png "スクリーンショット 2013-12-22 21.23.00.png")

## 3. 元の HentaiProject ターゲットに含まれる FirstViewController.m, SecondViewController.m をビルド対象に含めます。
(今回は SecondViewController.m は不要ですが、一応入れました。要は合体先のプロジェクトで使われる全クラスの実装ファイルをここに含めれば OK です。)

![スクリーンショット 2013-12-22 21.23.57.png](https://qiita-image-store.s3.amazonaws.com/0/747/cabeffa6-ebd5-2956-eb9b-6cd2a5f49b61.png "スクリーンショット 2013-12-22 21.23.57.png")
![スクリーンショット 2013-12-22 21.24.25.png](https://qiita-image-store.s3.amazonaws.com/0/747/f2f8f0f2-9113-fd9c-2541-b9e231d926f8.png "スクリーンショット 2013-12-22 21.24.25.png")

## 4. StaticHentai-Prefix.pch で UIKit を import します。

![スクリーンショット 2013-12-22 21.25.10.png](https://qiita-image-store.s3.amazonaws.com/0/747/8d52f6d8-388e-65a3-391e-badac9a99544.png "スクリーンショット 2013-12-22 21.25.10.png")


## 5. Storyboard を RubyMotion のプロジェクトの resources/ ディレクトリにコピーします。

```
$ cp vendor/HentaiProject/HentaiProject/Base.lproj/Main.storyboard resources
```

画像等を使う場合、同様にそれらもコピーしてください。


## 6. RubyMotion 側から利用する

Rakefile に以下を追加

```ruby:Rakefile
  # 中略
  app.vendor_project('vendor/HentaiProject', :xcode,
    :target => 'StaticHentai',
    :xcodeproj => 'HentaiProject.xcodeproj')
  # 後略
```

app/app_delegate.rb から FirstViewController を呼び出します。

```ruby:app/app_delegate.rb
class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    storyboard = UIStoryboard.storyboardWithName('Main', bundle: nil)
    @window.rootViewController = storyboard.instantiateViewControllerWithIdentifier('FirstViewController') # ここで指定しているのはクラス名ではなくて、Storyboard 上で割り振った Storyboard ID です。
    @window.makeKeyAndVisible
    true
  end
end

```

## 7. ほのぼの rake

![スクリーンショット 2013-12-25 20.55.52.png](https://qiita-image-store.s3.amazonaws.com/0/747/a380b978-d51a-4ffd-fed8-6e9d4237df52.png "スクリーンショット 2013-12-25 20.55.52.png")

ほら、で Qiita でしょ？

以下のリポジトリに今回のコードを置いておきます。参考にはならないと思いますが。。。

[satococoa/RubyMotion-AdventCalendar-2013](https://github.com/satococoa/RubyMotion-AdventCalendar-2013)