Skip to content
A RubyMotion UIViewController -> URL router
Ruby
Find file
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
app
lib
spec
.gitignore
Gemfile
README.md
Rakefile
Routable.gemspec

README.md

Routable

A UIViewController->URL router.

  @router.map("profile/:id", ProfileController)

  # Later on...

  # Pushes a ProfileController with .initWithParams(:id => 189)
  @router.open("profile/189")

Why is this awesome? Because now you can push any view controller from any part of the app with just a string: buttons, push notifications, anything.

Installation

gem install routable

And now in your Rakefile, require routable:

$:.unshift("/Library/RubyMotion/lib")
require 'motion/project'
require 'routable'

Motion::Project::App.setup do |app|
  ...
end

Setup

For every UIViewController you want routable with :symbolic params, you need to define .initWithParams({}).

class ProfileController < UIViewController
  attr_accessor :user_id

  def initWithParams(params = {})
    init()
    self.user_id = params[:user_id]
    self
  end
end

Here's an example of how you could setup Routable for the entire application:

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)

    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.makeKeyAndVisible

    # Make our URLs
    map_urls

    # .open(url, animated)
    if User.logged_in_user
      @router.open("menu", false)
    else
      @router.open("login", false)
    end

    true
  end

  def map_urls
    @router = Routable::Router.router
    @router.navigation_controller = UINavigationController.alloc.init

    # :modal means we push it modally.
    @router.map("login", LoginController, modal: true)

    # :shared means it will only keep one instance of this VC in the hierarchy;
    # if we push it again later, it will pop any covering VCs.
    @router.map("menu", MenuController, shared: true)
    @router.map("profile/:id", ProfileController)

    # :resets will reset the navigation stack with the target view controller
    @router.map("messages", MessagesController, resets: true)
    @router.map("message/:id", MessageThreadController)

    # can also route arbitrary blocks of code
    @router.map("logout") do
      User.logout
    end
    @router.map("logout/:id") do |params|
      User.logout(params[:id])
    end

    @window.rootViewController = @router.navigation_controller
  end
end

Configuration of View Controllers

If you need to configure a view controller before the router navigates to it, use a block:

# Configure and push an ImageEditorController
BW::Device.camera.any.picture(media_types: [:movie, :image]) do |result|
  router.open('editor') do |controller|
    controller.image = result[:original_image]
  end
end
Something went wrong with that request. Please try again.