プログラマブログ

by wacul

menu
  • プログラマ
  • RubyMotionを業務でのアプリ開発に使ってみた感想

2014.05.30RubyMotionを業務でのアプリ開発に使ってみた感想

こんにちわ。いまワカルでは、美容院向けのiPadアプリ “clulu” を開発中です。
テストも一旦終了し、最初のバージョンをApp Storeに申請したところです。

美容院では、お客様の予約管理を紙で行っているところがほとんどです。cluluは、そんな紙での管理方法から極力インターフェースを変えることなく、予約管理をiPadで行えるシステムです。また管理された情報を元に、リアルタイムに空き枠を検索・予約できるフォームを自分の美容院のホームページに設置できます。

clulu-ss

サービスの詳細については、リリース後詳しくお伝えするとして、今回はiPad版開発で使った、 RubyMotion について書きたいと思います。

なぜ RubyMotion を選んだか

iOSアプリ開発環境にはおおまかに

  • ObjectiveC(Xcode)
  • RubyMotion
  • Titanium, PhoneGap等、HTML,JSベースのもの

があります。

まず、cluluは予約表の操作感を最適化したかったため、画面のアニメーション等パフォーマンス調整の難しいHTMLベースのものは、候補からはずしました。

僕自身は、2,3年前にiOSのアプリの開発経験があり、ひと通りObjectiveCとiOSのSDKについては理解している状態でした。

過去のiOS開発から、ObjectiveCコードを書くことへの気の重さのようなことを感じていました。 Webの開発では、僕はEmacs,弊社の他のエンジニアもSublime Textなど、好みのエディタで開発している状態で、Xcodeの操作に慣れるというのもひとつの障壁です。

RubyMotionを選択するにあたって、情報不足や、予期せぬ不具合への対応などが不安でしたが、2013年末ごろにはかなりコミュニティも盛り上がってきていました。 また、基本的にCocoaのAPIをそのまま使う形なので、RubyMotion特有の不具合は少なそうというのも後押しとなり、RubyMotionで実装することに決めました。

まとめると、RubyMotionを選んだ理由は次の3つです。

  • iOSのSDKをそのまま使える (パフォーマンスの劣化が最小限、情報源が豊富)
  • ObjectiveCを書かなくてよい、 慣れたエディタで開発できる
  • コミュニティの盛り上がり (困ったときに参照する情報が十分にある)

実際に使ってみてよかった点

RubyのAPIの使いやすさ

RubyMotionは、Rubyの基本的な型のAPIがそのまま使えるようになっているため、Array#each,map などのコレクション系の操作がRubyライクに書けます。 もちろんブロックも使えるので、データの加工のコードなどが短く書けます

BubbleWrap, sugarcube便利

2つとも、CocoaのAPIをラップして使いやすくしてくれるライブラリです。 両者は似たような機能を提供している部分が多いですが、sugarcubeはBubbleWrapより、UIKitのクラス自身を拡張しにいっている感じになっています。

それぞれ、使いどころによって便利なほうを使って実装しました。 自然にかけるので、どちらかというとsugarcubeのほうが利用頻度高めでした。

特に便利だったものたち

1
2
3
4
5
6
7
8
9
10
11
12
13
### sugarcube
# RGB HexからUIColor
'#FBFBFB'.uicolor
# ImageNamed のかわり
'hogehogeimage'.uiimage
# タイマー
30.second.every do
  refresh()
end
# 日付の始まりの日
dateTime.start_of_day
# NotificationCenter
"SomeNotificationName".add_observer(self, :"onNotif:")

Mix-in便利

Rubyならではの便利さとして最も大きかったのが、Mix-inの活用です。

例えばよくあるDelegateを取るクラスを作るためのMix-inとして以下のようなものを作りました

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module Clulu
  module Delegation
    def delegate
      @delegate
    end

    def delegate=(d)
      @delegate = WeakRef.new(d)
    end

    # delegateが設定されていたら指定されたメソッドを呼び出す
    def delegateCall(selector, *args)
      if @delegate and @delegate.weakref_alive? and @delegate.respond_to?(selector)
        @delegate.send(selector, *args)
      end
    end
  end
end

Delegateを実装したいクラスは、 include Clulu::Delegation するだけです。

他にも、ローディングやエラー処理など、共通の挙動をViewControllerに付けたい場合などに使いました。 実装を注入できるのは便利です。

逆に大変だった点

サードパーティライブラリとの相性

基本的にCocoaPodsに登録されているライブラリ群はそのまま使えました。 一部、ObjectiveCのプロパティ定義を利用しているライブラリなど、そのままでは使えないものもあったので 薄いラッパを作って使いました。

メモリ管理

基本的にRubyMotionがメモリを自動で管理してくれるのですが、循環参照に関しては開放してくれないので、 適宜弱参照( WeakRef.new(hoge) )などを使って、循環参照が起きない用配慮する必要があります。 また、Rubyのブロックを使うと、外側のスコープの変数を束縛したままになるため、注意が必要でした。

コンパイル速度とタイプミス問題

一般的にコンパイル言語は型チェックや静的な解析をしてくれるので、早めにタイプミスなどが見つけやすい構造になっています。 しかしRubyMotionの場合は、コンパイルと起動にそれなりの時間がかかる一方、実行時まで定義されていない変数や、型の間違いがわからないため、タイプミスするとわーってなります。 僕はEmacsを使っているので、motion-mode と ac-dict を使ってある程度補完が効くようにはしていたのですが、 それでもCocoaの長いメソッド名とか、思わぬタイプミスでわーってなっていました。 ここらへんは宿命でしょうが、なかなかストレスでした。

まとめ

今回アプリ開発に携わったのは、僕( tutuming )と、kyoh の2名です。 kyoh君はiOSの開発自体が初めてだったのですが、苦労しつつも1ヶ月もしたら慣れたようでした。

個人的には特にRubyMotionだったから大変だったということはなかったです。 それ以上にiOSのSDKの使い方とか、実装面での苦労のほうが多いです。

1度ObjectiveCでアプリを書いたことがあり、RubyやPython,JavaScriptなど、Webっぽい言語も経験がある程度ある人であれば、スムーズに移行でき、少しだけ効率も上がる感じじゃないかなと思います。

RubyMotion3.0 (今年後半リリース予定)では、Androidにも対応する(同じくネイティブのラッパ)みたいなので、どんどん広がっていけばいいですね!

参考

この記事を書いた人tutuming

株式会社ワカルの技術責任者です。フロントエンドからバックエンドまで、ひと通りやってます。最近の興味はチームづくりと、パンづくりです。

waculでは、プログラマを募集しています。

現在はプロダクトとして、課題発見から改善提案まで自動で行うWeb改善プラットフォーム「AIアナリスト」を開発中です。

waculの採用情報へ

ページトップへ