Developer's Blog

RubyでiOSアプリ開発ができるRubyMotion

rubymotion_logo

東京で開発を担当している森本です。

みなさん楽しく iOS アプリつくっていますか?!最近の私はというと RubyMotion を使って iOS アプリをコツコツ作ることがささやかな楽しみになっています。

RubyMotion とは、元々 MacRuby を作っていた Apple のエンジニア Laurent Sansonetti さんが HipByte という会社をたちあげて作ったプロダクトです。 これを使うと、なんと Ruby で iOS や Mac のアプリを作ることができてしまいます。 Objective-C よりも Ruby が好きで、 iOS のアプリを Ruby で書けないのかなあなどと日々思っている方に、ぜひお勧めしたいプロダクトです。

今日は、この RubyMotion をご紹介したいと思います。

 

RubyMotion とは

名前から薄々感じさせているとおり RubyMotion を使うと Ruby で iOS や Mac アプリを作ることができてしまうのですが、もう少し細かく見ると以下の様な特徴があります。

・ Ruby で Objective-C のランタイム、 Foundation 、 iOS SDK などを直接操作することができる。
・ ビルドやデプロイ、テストの実行は全て rake コマンドでおこなう。
・ Ruby からマシン語に変換するので、ネイティブで動作するアプリケーションを作成できる。
・ もちろんメモリ管理のコードは不要。
・ Xcode を立ちあげなくても、自分の好きなエディタを使って全て開発できる。
・ InterfaceBuilder で編集した Storyboard 、 xib ファイルを利用可能。
・ 利用にはライセンスの購入が必要(2013年7月23日現在、日本円で¥20,790)。

Xcode と Objective-C の組み合わせも効率良くアプリを作成することができるようになってきていると思うのですが、 iOS SDK にある程度慣れている人であれば、好きなエディタと Ruby を使ってシンプルにコードを書ける RubyMotion を気に入るかもしれません。

 

コード

では実際、 Objective-C で書くコードが RubyMotion ではどのようなコードになるのでしょうか。以下にそれぞれのコード例をあげてみたいと思います。

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.viewController = [[BHViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
    self.window.rootViewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
    [self.window makeKeyAndVisible];
    return YES;
}
@end

 

よく見る Objective-C で書いた AppDelegate.m にあるコードですね。これが RubyMotion では次のようになります。

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.rootViewController = MainViewController.alloc.initWithNibName("MainViewController", bundle: nil)
    @window.makeKeyAndVisible
    true
  end
end

Objective-C の世界での書き方そのままに、 Ruby で書けるようにしている感ありありの奇妙なコードになってると感じるかもしれません。

もう一つ、 UIViewController のサブクラスを例にして、 RubyMotion ではどのようなコードになるのか見てみます。

class DeveloperViewController < UIViewController

  attr_accessor :textField

  def viewDidLoad
    super
    self.view.backgroundColor = UIColor.colorWithRed(0.945098, green: 0.933333, blue: 0.898039, alpha: 1)
    frame = self.view.bounds
    frame.size.height = 100
    frame.size.width = 250
    @textField = UITextField.alloc.initWithFrame(frame).tap do |t|
      t.borderStyle = UITextBorderStyleNone
      t.returnKeyType = UIReturnKeyDone
      t.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 130)
      t.textAlignment = UITextAlignmentCenter
      t.font = UIFont.systemFontOfSize(50)
      t.adjustsFontSizeToFitWidth = true
      t.delegate = self
    end
    self.view.addSubview @textField

    @label = UILabel.alloc.init.tap do |l|
      l.text = ''
      l.sizeToFit
      l.backgroundColor = UIColor.clearColor
      l.textColor = UIColor.grayColor
      l.center = CGPointMake(CGRectGetWidth(self.view.frame)/2, 140)
    end
    self.view.addSubview @label
  end

  def textFieldShouldEndEditing(textField)
    @label.hidden = !@textField.text.empty?
    self.parentViewController.performSelector('update_dictionary_view:', withObject: textField.text)
  end
end
&#91;/ruby&#93;

<p>7行目で view の背景色を指定していますが、キーワード引数がある Objective-C の世界のメソッドもそのままキーワード付きで記述します。また、デリゲートのメソッドも同じように書くことができます。</p>

<p>RubyMotion で Objective-C の世界で用意されたメソッドなどを利用する際は、素直にそのままキャメルケースで書く仕組みになっています。これについては先日おこなわれた RubyMotion Kaigi で、作者の Laurent さんが「 RubyMotion は Objective-C の世界を薄くラップする存在だ」と話しており、なんでも Ruby 側に寄せるのではなく、すでにある環境をできるだけそのまま使うことを意識して RubyMotion を作られているからのようです。</p>

<p>ただ、このキャメルケースとアンダースコアでつなぐ名前の付け方が混在してしまうことについては不満を感じている Rubyist も多いようで、より Ruby っぽく書くためのシンタックスシュガーを提供する gem を作っている方もいるようです。そういうものを使って部分的に Objective-C っぽさを排除することもできます。</p>

<p>また当然ですが Ruby のシンタックスで書いたコードも利用することができるので、普通に Ruby のコードで文字列処理やネットワークの処理を書いて、その結果をネイティブの API に渡すといったことができます。</p>

<!-- 段落本文ここまで -->
<p>&nbsp;</p>

<!-- 段落タイトルここから 以降、段落ごとに繰り返し -->
<h3 class="blue">学習コスト</h3>
<!-- 段落本文ここから -->
<p>Objective-C ではなく他の言語で iOS アプリを作るための仕組みには Titanium Mobile など様々存在していますが、 RubyMotion がそれらと異なるのは、 Objective-C の世界の API を Ruby のコードから直接実行することができるという点です。</p>
<p>Titanium Mobile のようにネイティブの環境をラップしたような独自の API が用意されているわけでないので、これまで培った iOS SDK の知識をそのまま流用することができます。これは iOS SDK の知識があれば、追加で余計な学習をする必要がないということです。</p>
<p>これまで Xcode を使って iOS のアプリを作っていた方にとっては乗り換えのコストが低いので、実は Ruby にも興味があるんだよ、という層にはとても興味深くうつるのではないでしょうか。</p>
<!-- 段落本文ここまで -->
<p>&nbsp;</p>


<!-- 段落タイトルここから 以降、段落ごとに繰り返し -->
<h3 class="blue">外部ライブラリの利用</h3>
<!-- 段落本文ここから -->
<p>Xcode 、 Objective-C の世界では、 <a href="http://cocoapods.org">CocoaPods</a> を使って便利なライブラリを手軽にプロジェクトに追加することができますが、 RubyMotion の世界でも、 RubyMotion 用に作られた gem が RubyGems からインストール可能なので、同じようにアプリへ便利なライブラリを追加することができます。 またそれだけではなく、 RubyMotion では既存の Objective-C ライブラリもそのまま利用することができます。もちろん CocoaPods もそのまま RubyMotion で利用可能です。</p>

<p>使い方は簡単です。 CocoaPods をセットアップしたあとに、 motion-cocoapods の gem を入れて、 RubyMotion のプロジェクトにある Rakefile に pod を追記していきます。</p>

[ruby]
require 'rubygems'
require 'motion-cocoapods'

Motion::Project::App.setup do |app|
  app.pods do
    pod 'JSONKit'
  end
end

Rakefile にこのように記述しておいて、あとは rake コマンドでビルドすると、自動的にライブラリが追加される仕組みです。 RubyMotion では最終的にネイティブで動作するマシン語へコンパイルされるので、そういうこともできてしまうんですね。 Objective-C の世界の既存のライブラリがそのまま利用できるというのは、これまで Xcode でいろんなライブラリを使いながら iOS アプリを作っていた人にとって嬉しい限りです。

 

まとめ

このように、 RubyMotion を使った iOS アプリ開発では、 Objective-C を Ruby に置き変えつつも、これまでの経験はそのまま活用することができるところが大きな特徴です。 Objective-C を使って iOS アプリを作っている時に、これを Ruby でかけたら…と思ったことがある人にピッタリのものだと思います。既存のノウハウがそのまま使えるため、乗り換えのコストも非常に低いのもいいですね。

その他、 RubyMotion にはもっと多くの機能があります。 RubyMotion の公式 Web ページはもちろん、有志の方が作成されたチュートリアルページを参照すると効率よく学習することができます。

また、2013年5月29日には RubyMotion Kaigi が渋谷で開催されました。そのときの様子はリンク先のページで動画として公開されています。この RubyMotion Kaigi では、作者の Laurent Sansonetti さんが来日して講演し、 RubyMotion の未来についても話していました。そこでは iOS と OS X 以外にも新しいプラットフォームに対応予定だという意味深な発表もありました。もしかして、 iOS ではない、もうひとつの有力スマートフォン向け OS がサポートされたりするのでしょうか?!詳細は不明ですが、 RubyMotion から引き続き目が離せません。

いかがでしたでしょうか。興味を持たれた方はぜひ使ってみてください。

それでは明日も楽しい iOS アプリ開発を!

 

//

 

Copyright © 2019 Fenrir Inc. All rights reserved.