RubyMotion Tutorial for Beginners: Part 1
In this RubyMotion Tutorial for beginners, you’ll learn how to make a simple Pomodoro app for the iPhone. By Gavin Morrice.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
RubyMotion Tutorial for Beginners: Part 1
25 mins
- Getting Started
- Differentiating RubyMotion vs. Ruby
- Introducing Pomotion
- Gemfile
- Rakefile
- Overriding Configuration Options
- The “app” Directory
- The “build” Directory
- The “resources” Directory
- The “spec” Directory
- Hello World Example
- Adding a Main View Controller
- Pixate Freestyle
- Adding Views Programmatically
- Getting the Timer to Count Down
- Importing C Code into Your Project
- Where To Go From Here?
The “app” Directory
app is where most of your application’s code should live; you’ll store your views, controllers, and models there. RubyMotion will automatically load all files in this directory with a .rb
extension.
The “build” Directory
build by default will contain all of your compiled code; you create it the first time you run rake
against your project. However, you can specify an alternate directory for your compiled code in the build_dir
parameter of your Rakefile.
From time to time you might want to clear the build directory and rebuild the whole application from scratch; simply run rake clean
within your project directory in Terminal to accomplish this.
The “resources” Directory
resources is where you add any extra resources to your bundle, including icons, images, fonts and other files.
The “spec” Directory
spec is where you store specs, or tests, for your app. The Ruby community has a long-established culture of writing well-tested code, which includes writing the tests before writing any code.
You won’t cover Ruby tests in this tutorial — that’s a whole other subject best left for another time! :]
Hello World Example
No tutorial would be complete without a “Hello World” example, and this one is no exception.
Open app/app_delegate.rb and add the following lines above application:didFinishLaunchingWithOptions
:
def hello_world_label
@hello_world_label ||= begin
frame = CGRectMake(20,200,280,40)
label = UILabel.alloc.initWithFrame(frame)
label.text = "Hello world"
label.textColor = UIColor.whiteColor
label.textAlignment = UITextAlignmentCenter
label
end
end
def window
@window ||= UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
end
Here’s what the above code does:
First, you define a method named hello_world_label
, which is a getter method for a UILabel that the app will display on the screen. Unlike a standard getter though, which would simply return the value of @hello_world_label
, this method goes a step further. The ||=
(or-equals) operator here means “if the variable on the left is truthy return its value; otherwise execute the code to the right of the operator and assign its value to the variable for future calls”.
This is a great way to lazy-load a property in that its value is only set when you actually call the method; in addition, this is a memoized method which caches its value, making future calls to this method execute faster.
Next, you define a method named window
, which returns the main UIWindow object for this application. Again, you use the ||=
operator to set a default value if one is not already set.
Note: The name of this method is hello_world_label
, not helloWorldLabel
as you might be used to seeing. Why?
In Objective-C, you usually write method variable names in CamelCase
; in Ruby it’s general practice to write them in snake_case
. Since RubyMotion is a hybrid between the two, you’ll often see RubyMotion developers use either CamelCase or snake_case: there doesn’t seem to be an agreed upon convention.
What’s my preference? Both! :] When writing code that’s part of the iOS API such as when defining a tableView:cellForRowAtIndexPath
method, I’ll use CamelCase — even for the parameters — since that’s how it was defined in the API. I’ll use snake_case with code that’s specific to the application. This clearly delineates my code from iOS API code — and it means I can re-use my plain old Ruby classes in other non-RubyMotion applications without having to modify them.
Note: The name of this method is hello_world_label
, not helloWorldLabel
as you might be used to seeing. Why?
In Objective-C, you usually write method variable names in CamelCase
; in Ruby it’s general practice to write them in snake_case
. Since RubyMotion is a hybrid between the two, you’ll often see RubyMotion developers use either CamelCase or snake_case: there doesn’t seem to be an agreed upon convention.
What’s my preference? Both! :] When writing code that’s part of the iOS API such as when defining a tableView:cellForRowAtIndexPath
method, I’ll use CamelCase — even for the parameters — since that’s how it was defined in the API. I’ll use snake_case with code that’s specific to the application. This clearly delineates my code from iOS API code — and it means I can re-use my plain old Ruby classes in other non-RubyMotion applications without having to modify them.
Still in the same file, update application:didFinishLaunchingWithOptions:
so that it looks like the following:
def application(application, didFinishLaunchingWithOptions: launchOptions)
window.addSubview(hello_world_label)
window.makeKeyAndVisible
true
end
Here you add hello_world_label
as a subview to the window
object and tell the application to make the window
object visible.
Save your work, then switch over to Terminal and run the following command:
rake
In a few seconds you’ll see your shiny new RubyMotion “Hello World” app running in the iOS Simulator as below:
Type exit
in Terminal to stop both Rake and the simulator.
That takes care of your Hello World app; you can now take your new-found knowledge and press on with building Pomotion.
Adding a Main View Controller
Your first task in Pomotion is to create a main view-controller for the main screen.
To keep things organized — and to stay in line with Ruby on Rails’ file structure — you’ll create a new directory to store your controller files.
Return to Terminal and run the following command:
mkdir app/controllers
This creates a new directory controllers inside the existing app directory.
Run the following command in Terminal:
touch app/controllers/main_view_controller.rb
This creates a new file for your view controller.
Open main_view_controller.rb and add the following code:
class MainViewController < UIViewController
end
The code above creates a class MainViewController
that inherits from UIViewController
. Note that you've kept the same name for your controller class as the file that contains your class.
Next, return to app_delegate.rb and delete the entire hello_world_label
method along with the code you added in application:didFinishLaunchingWithOptions:
; they won't be required for Pomotion.
Your complete app_delegate.rb should now look like this:
class AppDelegate
def window
@window ||= UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
end
def application(application, didFinishLaunchingWithOptions:launchOptions)
true
end
end
Now, add the following code to app_delegate.rb:
def main_view_controller
@main_view_controller ||= MainViewController.alloc.initWithNibName(nil, bundle: nil)
end
def navigation_controller
@navigation_controller ||= UINavigationController.alloc.
initWithRootViewController(main_view_controller)
end
Here you simply create getter methods for the MainViewController
and a UINavigationController
to present it.
Finally, add the following to application:didFinishLaunchingWithOptions:
:
def application(application, didFinishLaunchingWithOptions:launchOptions)
window.rootViewController = navigation_controller
window.makeKeyAndVisible
true
end
In the code above you tell window
to display navigation_controller
and become visible.
Run rake
in Terminal to launch the simulator:
For now, all you'll see is a UINavigationBar
with a blank screen; The window
is loading navigation_controller
as expected, but the displayed view is transparent.
One option is to create them in code, like you'll do in this tutorial. A second option is to use Interface Builder with RubyMotion - to learn how to do that, check out this GitHub page.
One option is to create them in code, like you'll do in this tutorial. A second option is to use Interface Builder with RubyMotion - to learn how to do that, check out this GitHub page.