Google+ もご覧ください
ユーザーアイコン

実践!RubyMotion

第八回 RubyMotion で Interface Builder を使うには?

Satococoa

第八回 RubyMotion で Interface Builder を使うには?

今回は RubyMotion で Xcode の Interface Builder を使う方法について説明したいと思います。

RubyMotion と Interface Builder

実は Interface Builder でつくった *.storyboard ファイルや *.xib ファイルを resources ディレクトリに置いておくだけで、rake コマンドでアプリケーションをビルド時にそれぞれ *.storyboardc、*.nib ファイルに自動的にコンパイルします。そのため、デフォルトでも RubyMotion では Interface Builder を使用して UI をつくることができます。

しかし RubyMotion 標準の機能だけでは Xcode のように Storyboard 上に置かれた IBOutlet や IBAction を通じてコードと直感的に結びつけることができないため、Interface Builder 上で tag を付け、viewWithTag メソッドを使ってコードから UI パーツを参照するなどの直感的ではない方法を使わなくてはなりません。

そこで ib gem の出番となります。

ib

ib gem を利用すると、RubyMotion のコードと Interface Builder 間の連携をスムーズに行えるようになります。

早速使ってみましょう。

インストール

まずは新しいプロジェクトをつくります。

$ motion create IBSample
    Create IBSample
    Create IBSample/.gitignore
    Create IBSample/app/app_delegate.rb
    Create IBSample/Gemfile
    Create IBSample/Rakefile
    Create IBSample/resources/Default-568h@2x.png
    Create IBSample/spec/main_spec.rb

次に ib gem をインストールします。いつも通り Gemfile に以下の一行を記入し、bundle コマンドでインストールしてください。

$ cd IBSample
$ vim Gemfile
  # gem 'ib' の一行を追加
$ bundle
Fetching gem metadata from https://rubygems.org/............
Resolving dependencies...
Using rake (10.1.0)
Using i18n (0.6.9)
Using multi_json (1.8.2)
Installing activesupport (3.2.16)
Using colored (1.2)
Using thor (0.18.1)
Using tilt (2.0.0)
Using xcodeproj (0.14.1)
Using ib (0.4.3)
Using bundler (1.3.5)
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

Storyboard ファイルの作成

ib gem をインストールすると、以下の 2 つの rake タスクが追加されます。

$ rake -T
# ...(略)
rake ib:open                      # Generates ib.xcodeproj and opens it in XCode <- これと
rake ib:project                   # Generates ib.xcodeproj <- これ!
# ...(略)

これらのタスクを実行することで、Storyboard, xib ファイルを作成するためのダミーの Xcode プロジェクトがつくられます。

rake ib:project

これで ib.xcodeproj という Xcode プロジェクトがつくられました。ディレクトリ構造は以下のようになっていると思います。

../IBSample
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── app
│   └── app_delegate.rb
├── ib.xcodeproj
│   ├── Stubs.h
│   ├── Stubs.m
│   └── project.pbxproj
├── resources
│   └── Default-568h@2x.png
└── spec
    └── main_spec.rb

4 directories, 9 files

次のコマンドを実行すると Xcode が開きます。

rake ib:open

rake ib:open を実行
rake ib:open を実行

まだ Storyboard のファイルはつくられていませんので、Xcode 上で Storyboard を作成してみます。

メニューから File -> New -> File... とたどり、User Interface のカテゴリから Storyboard を選択します。

Storyboard を作成1
Storyboard を作成1

Storyboard ファイルの保存先のグループには Resources を指定してください。Xcode に慣れていないと少し分かりにくいのですが、この Resources グループにファイルを入れると ./resources フォルダの中に保存されます。

Storyboard を作成2
Storyboard を作成2

簡単な画面遷移の作成

早速 Storyboard を使って簡単な画面遷移を作ってみます。Storyboard の基本的な操作は割愛します。

以下のような手順で Storyboard 中に 2 つの View Controller を作ってください。

  1. View Controller を 2 つ置く
  2. それぞれの View Controller にラベルを置きテキストを A、B とする
  3. A の View Controller の view に Button を追加する
  4. Button から View Controller B に向かって ctrl + ドラッグし、modal の Action Segue を定義する

Storyboard を作成3
Storyboard を作成3

上記のスクリーンショットではついでに背景色も変えています。

作成した Storyboard を読み込む

作成した Storyboard を読み込んで画面を表示させてみましょう。app/app_delegate.rb を以下のように編集します。

app/app_delegate.rb

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    storyboard = UIStoryboard.storyboardWithName('Storyboard', bundle: nil)
    @window.rootViewController = storyboard.instantiateInitialViewController
    @window.makeKeyAndVisible
    true
  end
end

いつもの rake コマンドで起動してみます。

Storyboard を読みこんで起動
Storyboard を読みこんで起動

真ん中のボタンをタップすると画面遷移し、B のラベルの載った View Controller が現れるはずです。

戻る動作を定義

B のラベルがある方の View Controller にボタンを置いて、そのボタンをタップすると元の A に戻るようにしましょう。Storyboard 上の View Controller に対応するコードをつくります。

(ボタンへの参照はこのサンプルの場合は必要がありませんが、例示のために outlet を作成しています。)

app/first_controller.rb

class FirstController < UIViewController
  outlet :open_button, UIButton

  def viewDidLoad
    super
    # 参照できていることを確認するため
    p open_button
  end
end

app/second_controller.rb

class SecondController < UIViewController
  outlet :close_button, UIButton

  def viewDidLoad
    super
    # 参照できていることを確認するため
    p close_button
  end

  def close(sender)
    self.dismissViewControllerAnimated(true, completion:nil)
  end
end

ファイルを作成したら、 再び rake ib:open コマンドを実行してください。

実はこの rake ib:open タスクですが、単に Xcode のプロジェクトを開くだけのコマンドではありません。開かれた Xcode プロジェクト内の Supporting Files/Stubs.h というファイルを見ると、先ほど RubyMotion で定義したクラスやメソッド、IBOutlet が定義されているのが分かると思います。

一方、実装ファイルの Stubs.m を見ると空っぽです。つまり ib gem は RubyMotion のコードからダミーの Objective-C コードを書き出し、Interface Builder で参照できるようにしてくれているのです。

あとは通常の Objective-C で Interface Builder を使っているときと同様に Outlet や Action をつないでみます。まずは A のラベルを置いた View Controller に FirstController、B の方に SecondController を割り当てます。

Custom Class を指定
Custom Class を指定

つづいて FirstController、SecondController のアウトレットをつなぎ、SecondController の Close ボタンに close: アクションを割り当てましょう。

Storyboard と接続
Storyboard と接続

ここまでできたら rake で実行してみてください。無事、閉じるボタンも動作すると思います。

Unwind Segue を使う

先ほどのコードでは戻る動作を dismissViewControllerAnimated:completion: メソッドを使って実装しましたが、戻る動作の segue である "Unwind Segue" も RubyMotion で使用することが出来ます。

Unwind Segue は戻り先のコントローラで定義します。

FirstController に以下の close: メソッドを定義し、このメソッドを Unwind Segue として使用できるように ib_action メソッドの第二引数で UIStoryboardSegue * 型の引数を取ることを宣言します。

class FirstController < UIViewController
  extend IB
  ib_action :close, UIStoryboardSegue
  # (中略)
  def close(sender)
    p 'closed with segue!'
  end
end

また、SecondController に宣言した close: メソッドを削除しておきましょう。

続いて rake ib:open コマンドで再度 Xcode を開きます。Stubs.h を見ると、以下のように FirstController に close: メソッドが定義されているのが確認できると思います。

-(IBAction) close:(UIStoryboardSegue*) sender;

一点、ib を使う上での注意点なのですが、削除した action や outlet への参照が自動で消えてくれたりはしませんので、先ほど削除した SecondController の close: メソッドへの参照を Storyboard から手動で削除する必要があります。close ボタンをクリックし、忘れずに close: メソッドへの参照を削除してください。

改めて、FirstController の close: メソッドを使うように参照をつくります。ctrl キーを押しながら close ボタンから右下にある緑色のボタンに向かってドラッグしてください。以下のスクリーンショットのように Unwind Segue として close: ボタンを指定できると思います。

Unwind Segue を接続
Unwind Segue を接続

では再度 rake コマンドでアプリケーションを実行してみましょう。

Unwind Segue を使って動作している様子
Unwind Segue を使って動作している様子

正しく動きましたでしょうか?

まとめ

今回は RubyMotion から Storyboard を使う方法について解説しました。同様に *.xib も扱うことが出来ますので、うまくコードと xib、Storyboard を使い分けて効率的にアプリケーションを開発していきましょう。

今回のサンプルは 8-ib-gem.zip です。

Rubymotion
タグ:

記事をリクエストする

関連記事

コメント