Web & iOS dev – Ruby, Rails, RubyMotion & React

Paul Sturgess

How to Debug Core Data Output to the Console in RubyMotion

Core Data can show you the underlying queries and execution times whilst you are running your app. Just fire it up with:

rake args="-com.apple.CoreData.SQLDebug 1"

Note you can bump the number up to 2 or 3 depending on how much information you want. 3 goes as far as to show you the result set Core Data has fetched.

Setting the Status Bar Colour for iOS7 in RubyMotion

First things first you need to set UIViewControllerBasedStatusBarAppearance in your info.plist.

This is done by updating your Rakefile like so:

app.info_plist['UIViewControllerBasedStatusBarAppearance'] = true

Now you need to implement the method preferredStatusBarStyle in your subclassed UINavigationController:

class MyCustomNavigationController < UINavigationController

  def preferredStatusBarStyle
    UIStatusBarStyleLightContent
  end

end

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.makeKeyAndVisible
    controller = YourFirstController.alloc.init
    @window.rootViewController = MyCustomNavigationController.alloc.initWithRootController(controller)
    return true
  end
end

Note that UIStatusBarStyleLightContent will turn your status bar text color to white.

How to Use the Crittercism Cocoapod in a RubyMotion App

Crittercism is a great way of collecting data and crash reports from your iOS application whilst it’s being used in realtime.

The easiest way to get it up and running in your RubyMotion app is to use the Coacoapod.

If you haven’t setup Coacoapods in your app yet then check out my article where I install the ViewDeck Cocoapod.

Update your Rakefile with:

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

  app.frameworks += [
    'SystemConfiguration'
  ]

  app.pods do
    pod 'CrittercismSDK'
  end
end

Locate your Crittercism App id under Settings on the Crittercism website. Update your app_delegate.rb with the following just before you call makeKeyAndVisible:

crittercism_app_id = "51d1421f97c8f273e0000007"
Crittercism.enableWithAppID(crittercism_app_id)

Now when you build your app and errors get raised, you’ll start receiving crash reports.

How to Memory Profile a RubyMotion Application Using Instruments

Instruments, to quote Apple, “is a performance, analysis, and testing tool for dynamically tracing and profiling OS X and iOS code”.

Essentially it gives you live data while your application is running to help track down memory leaks and performance issues.

Profiling in the simulator

Simply fire your application up and then open Xcode. Open Instruments via the menu:

Xcode > Open Developer Tool > Instruments

Once Instruments had opened, I elected to keep the icon in the dock. This just saves having to open Xcode each time I want to run Instruments.

Once you’ve chosen the type of profiling you want to perform, from the Choose Target dropdown select, select Attach to Process. Under the System heading you should see the name of your app to select.

Finally hit the record button and you’re good to go.

Profiling whilst your app is running on your device

First up make sure your device is recognised by Xcode to be “used for development”.

If you haven’t done this, connect your device to your computer and open Xcode and open the organiser via:

Xcode > Window > Organizer

Find your device and select “Use for development”

Now in Instruments you should be able to select your iPhone as a target. Then under Choose Target you should get a list of your apps to choose from.

Note that your application must have been provisioned using a development profile.

How to View the RubyMotion Release Notes

Presuming you have RubyMotion installed. This one-liner should open the release notes in your favourite editor:

$ open /Library/RubyMotion/NEWS

How to Setup TestFlight for a RubyMotion App

The official RubyMotion guide for installing TestFlight got me most of the way there, but there were a few additional steps I needed to get everything working.

First and foremost I got my app running on my own device via usb.

However, for TestFlight, an Adhoc Provisioning Profile is required, as opposed to a Development Provisioning Profile. Essentially this is an Apple approved license to distribute your app to a limited number of devices without using the App Store.

Create a distribution certificate

Go to the Apple iOS developer website and create a Distribution certficate in a similar way to how you created your Developer certificate.

Create a fixed App ID

This is optional, but it felt right to me to use a fixed App ID instead of a wildcard.

Create an adhoc distribution profile

Finally, still on the Apple iOS Developer website, create an Adhoc distribution profile, download it and double click it to install it.

Setting up your Rakefile for multiple environments

I wanted to use both my Developer and Adhoc Provisioning Profiles at the same time. Without having to worry about switching them when required.

My Rakefile looks like this:

Motion::Project::App.setup do |app|
  env = if ENV['adhoc'] == '1'
          'adhoc'
        else
          'dev'
        end

  app.name = 'MyApp'

  # Provisioning profiles
  if env == 'adhoc'
    app.identifier = 'com.mydomain.myapp'
    app.codesign_certificate = 'iPhone Distribution: Company (XXXXXXXXXX)'
    app.provisioning_profile = '/path/to/adhoc/provisioing/profile/example.mobileprovision'
    app.entitlements['get-task-allow'] = false
  else
    app.identifier = 'com.mydomain.myapp'
    app.codesign_certificate = 'iPhone Developer: My Name (XXXXXXXXXX)'
    app.provisioning_profile = '/path/to/development/provisioing/profile/example.mobileprovision'
  end

  # TestFlight config
  app.testflight.sdk = 'vendor/TestFlight'
  app.testflight.api_token = 'sometoken'
  app.testflight.team_token = 'anothertoken'
end

desc "Set the env to 'adhoc'"
task :set_adhoc do
  ENV['adhoc'] = '1'
end

desc "Run Testflight with the adhoc provisioning profile"
# e.g. rake tf notes="My release notes"
task :tf => [
  :set_adhoc,
  :testflight
]

Credit to Hwee-Boon Yar for writing up how to setup the Rakefile for multiple environments

Your API token is under your account settings on TestFlight at: https://testflightapp.com/account/#api.

You can find your team API token at the following url: https://testflightapp.com/dashboard/team/edit/

One key bit of information I was initially missing was setting get-task-allow to false. This is only required for the Adhoc Provisioning Profile.

Use a custom rake task to deploy to TestFlight

Notice the rake task at the bottom sets the adhoc variable to ensure the Adhoc provisioning profile is used before firing off the TestFlight task added by motion-testflight.

So from now on I release to TestFlight via:

$ rake tf notes="My release notes"

How to Setup a Test Only Group in Bundler for RubyMotion

Coming from a Ruby on Rails background, it’s common place to see the Gemfile declarations in logical groups. This ensures your gems only get required in the environment they are needed.

A similar setup can be achieved in RubyMotion by tweaking your Gemfile and Rakefile.

In your Gemfile:

source "https://rubygems.org"
gem 'rake'
gem 'motion-cocoapods'

group :spec do
  gem 'motion-redgreen'
end

In your Rakefile:

if ARGV.join(' ') =~ /spec/
  Bundler.require :default, :spec
else
  Bundler.require
end

Thanks to the TinyMon application where I first saw this setup.

Using Native Objective-C Cocoapod Libraries in RubyMotion

Whilst RubyMotion is new, and the number of RubyMotion specific libraries is growing fast, there are already loads of native Objective-C libraries out there.

These instructions show you how to use Cocoapods in combination with Bundler.

Cocoapods is a dependency manager, like RubyGems, but for Objective-C projects.

In this example, I’ve chosen to install ViewDeck. ViewDeck makes it easy to implement the sliding panel user interface made popular by the Facebook iOS app.

The CocoaPods website is a great place to search for available ‘Pods’.

Summary of steps

  • Include the motion-cocoapods gem
  • Setup Cocoapods
  • Add ViewDeck to your application Rakefile

Bundler

If you haven’t got Bundler setup, I’ve written some instructions for using Bundler with RubyMotion.

Cocoapods

Add cocoapods to your Gemfile:

gem 'motion-cocoapods'

Install the gem via bundler:

$ bundle

Setup Cocoapods via:

$ pod setup

Add ViewDeck to your Rakefile

In your Rakefile you need to add the ViewDeck pod and QuartzCore Framework (required by ViewDeck):

Motion::Project::App.setup do |app|
  # Frameworks
  app.frameworks += [
    'QuartzCore'
  ]

  # Cocoapods
  app.pods do
    pod 'ViewDeck'
  end
end

Finally tell motion-cocoapods to download your dependencies by running:

$ rake pod:install

ViewDeck will be automatically built and linked the next time you build your app.

In future you can grab updated versions by running:

$ rake pod:update

Using ViewDeck

I’ve ported the Objective-C example ViewDeck application over to RubyMotion.

Feel free to check it out.

Setting Up Bundler and RVM for a RubyMotion App

Create your rvm .ruby-version and .ruby-gemset files via:

$ rvm use 1.9.3@yourgemsetname --create --ruby-version

Add bundler to your Rakefile

require 'bundler'
Bundler.require

Create your Gemfile via:

$ bundle init

Update your Gemfile

source "https://rubygems.org"
gem "your-favourite-gem"

Install gems via:

$ bundle

You’re done.

Using RubyMotion to Provision an App Onto Your iPhone

So you’ve got your Apple developer account and now you want to get your RubyMotion app onto your iPhone.

At the end of these instructions you will be able to deploy multiple apps using the same provisioning profile. Ideal for prototyping.

Summary of what you need to do

  • Generate an iOS certificate
  • Create an App ID
  • Register your iPhone with your Apple Developer account
  • Create a Provisioning Profile
  • Update your RubyMotion Rakefile to use the Certificate and the Provisioning Profile

Generate an iOS certificate

Open the Keychain Access program on your Mac and from the dropdown menu choose:

Keychain Access > Certificate Assistant > Request a certificate from a certificate authority

The ‘common name’ is the name for your private key. You can choose whatever you like.

Just make sure you select to save to disk.

Now you need to sync this up with your Apple Developer account.

Visit The Apple iOS Dev Centre and go to the Certificates, Identities & Profiles section.

Go to Certificates > Development and select to add a new certificate. Follow the step process, uploading the certificate you just created.

At the end you need to download the .cer file that gets generated. Double click it to add to your Keychain.

Create an App ID

In that same section of the website you can create an App ID by going to Identifiers > App ID's.

I opted for the Wildcard App ID. The wildcard ID means I don’t need to create a new App ID & Profile for each new app I want to try out on my iPhone.

Obviously when it comes to App Store submission, then it will make sense to have a dedicated App ID. Also Apple recommend a dedicated App ID if you’re testing advanced features like Push Notifications.

Register your iPhone with your Apple Developer account

Again staying on the iOS Dev Center website, you need to register all the devices you want to deploy your app onto.

You only need to do this once for each device, but you’ll need to know the UDID for each one.

You can get your UDID by plugging your iPhone into your computer via a USB cable and firing up Xcode. It’s labelled as Identifier on the details screen that lists the model and serial number etc.

Create a Provisioning Profile

The last task on the iOS Dev Center website is to create a Development Provisioning Profile.

All the instructions are self-explanatory so I won’t repeat them here. Essentially you are combining the certificate, the App ID and the Device ID(s) that you have setup.

Just make sure you download and double click the .mobileprovision file at the end.

Update your RubyMotion Rakefile to use the Certificate & Provisioning Profile

Update your Rakefile in your app:

Motion::Project::App.setup do |app|
  app.name = 'ExampleApp'
  app.identifier = 'com.yourdomain.exampleapp'
  app.codesign_certificate = 'iPhone Developer: Your Name (XXXXXXXXXX)'
  app.provisioning_profile = '/path/to/your/provisioning/profile/Example_App.mobileprovision'
end

Note that Wildcard App Id means you can use any name for the third part of the identifier.

Also for the codesign_certificate, you can view this in the Keychain Access program.

Finally deploy to the device via:

$ rake device