RubyMotionアプリでStoryboardとIBのアウトレット+アクションを使う話

最近RubyMotionさわりはじめたので覚えたことをtipsとして書きます。

Storyboardを導入する

RubyMotion で Storyboard を使う - toshikazu horii's blog

https://github.com/HipByte/RubyMotionSamples/tree/master/ios/StoryboardCustoms

が参考になる。

セットアップは基本的にこのとうりでいいんだけど、

# app/app_delegate.rb
class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)

    @storyboard = UIStoryboard.storyboardWithName('StoryboardExample', bundle:nil)

    @window.rootViewController = @storyboard.instantiateViewControllerWithIdentifier('TopTab')
    @window.rootViewController.wantsFullScreenLayout = true
    @window.makeKeyAndVisible

    true
  end
end

はこうも書ける。

# -*- coding: utf-8 -*-
# Rakefile
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project/template/ios'

Motion::Project::App.setup do |app|
  # Use `rake config' to see complete project settings.
  app.name = 'StoryboardSample'
  app.info_plist['UIMainStoryboardFile'] = 'StoryboardExample'
end
# app/app_delegate.rb
class AppDelegate
  attr_accessor :window

  def application(application, didFinishLaunchingWithOptions:launchOptions)
    true
  end
end

resources/StoryboardExample.storyboard が上記チュートリアルのとうりあらかじめ必要。

アウトレット+アクション

このままだとrubyで書いてるViewControllerクラスはXcodeから当然読み込めないのでアウトレットの接続などができないままです。

viewDidLoad とかからコードでUIコンポーネント生成していくのが普通みたいだけど、せっかくStoryboardを使っているのに残念な感じです。

Basecamp for iPhoneなどもInterface Builder使わずに作ったらしいけど*1、過去の体験からViewContorllerには一切余計なコードを入れずに分離したい派なのでなんとかできないかと試行錯誤したところ、ib っていうライブラリを使うと簡単にできたので以下にやり方を書きます。

https://github.com/yury/ib

gem install ib

インストールすると

rake -T
    rake ib:open               # Generates ib.xcodeproj and opens it in XCode
    rake ib:project            # Generates ib.xcodeproj

が使えるようになる

rake ib:open

でダミーのxcodeprojectが作成され。スタブのObjective-Cクラスにrubyで定義したアウトレットとアクションをXcoe経由で接続できるようになる。

# app/detail_controller.rb
class DetailController < UIViewController
  extend IB
  outlet :button, UIBarButtonItem

  def toggleColorAction sender
    view.backgroundColor = UIColor.colorWithRed(rand(100)*0.01, green: rand(100)*0.01, blue: rand(100)*0.01, alpha: 1.0)
  end
end

これが

こんな感じに

接続できた。

意味はないけどToggleボタンを押す度に背景色がランダムに変ります。

ソース

https://github.com/laiso/RubyMotionSamples/tree/master/StoryboardSample

ソースここに置いておきますね。