Watson's Blog

Creating an iOS Application Using RubyMotion

| Comments

In this article I will explain how to create a simple iOS application using RubyMotion. I will call this application “StopWatch”, and MacRuby version of this application is explained in “Creating a simple application”.

The “StopWatch” application has the following features.

  • This application has the user interface which are start buttion, stop button and label.
  • Run the timer if the start button is clicked.
  • Stop the timer if the stop button is clicked.
  • The timer value is displayed in the label.

Creating a New Application

The command-line interface is created as /usr/bin/motion if you install RubyMotion. Runs as following command in Terminal, you may create the application template.

1
2
3
4
5
6
7
8
9
$ motion create StopWatch
    Create StopWatch
    Create StopWatch/.gitignore
    Create StopWatch/Rakefile
    Create StopWatch/app
    Create StopWatch/app/app_delegate.rb
    Create StopWatch/resources
    Create StopWatch/spec
    Create StopWatch/spec/main_spec.rb
  • Rakefile: This file contains the configuration of the project, as well as a default set of tasks.
  • app: This directory contains the Ruby code of the project.
  • resources: This directory contains the resources files of the project, such as images or sounds.
  • spec: This directory contains the specification files of the application.

You can know detail of the configurations with Project Management.

Implements the application

Opens the app/app_delegate.rb with your editor.

1
2
3
4
5
class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    true
  end
end

Implements the code which contains actions or user interface for iOS into this file. UIKit Framework Reference may help you to implement user interface.

1. Create the UIWindow object

First step, creates the UIWindow object. The UIWindow class defines objects that manage and coordinate the windows an application displays on the screen.

1
2
3
4
5
6
7
8
9
10
11
class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)

    # Sets the StopWatchViewController as rootViewController
    @window.rootViewController = StopWatchViewController.alloc.init

    @window.makeKeyAndVisible
    true
  end
end

Sets the StopWatchViewController which inherited the UIViewController as rootViewController. The UIViewController provides basic functions for view-management.

2. Implement the StopWatchViewController

Prepares the StopWatchViewController as following.

1
2
3
4
class StopWatchViewController < UIViewController
  def viewDidLoad
  end
end

viewDidLoad method is called after the controller’s view is loaded into memory. Implements the user interface into viewDidLoad method. The UIView is used when lays out the user interface. You may retrive the UIView as following.

1
2
3
4
5
6
7
8
9
# retrive the UIView
view = self.view
# configure background color
view.backgroundColor = UIColor.whiteColor

# retrive the screen size
frame = view.bounds
height = frame.size.height
width  = frame.size.width

Lays out the user interface

Creates the user interface object after retriving the UIView, and you may lay out the user interface that invokes addSubview.

Let’s lay out the start/stop button and label.

Lays out the start button
1
2
3
4
5
6
7
8
9
10
11
# start button
@start = UIButton.buttonWithType(UIButtonTypeRoundedRect)
@start.frame = CGRectMake(0, 300, width/2 - 20, 30)
@start.setTitle("start", forState: UIControlStateNormal)

# connect an action method for start button
@start.addTarget(self,
                 action: "startTimer:",
                 forControlEvents: UIControlEventTouchUpInside)

view.addSubview(@start)
Lays out the stop button
1
2
3
4
5
6
7
8
9
10
11
# stop button
@stop = UIButton.buttonWithType(UIButtonTypeRoundedRect)
@stop.frame = CGRectMake(width/2 + 20, 300, width/2 - 20, 30)
@stop.setTitle("stop", forState: UIControlStateNormal)

# connect an action method for stop button
@stop.addTarget(self,
                action: "stopTimer:",
                forControlEvents: UIControlEventTouchUpInside)

view.addSubview(@stop)
Lays out the label
1
2
3
4
5
6
# label for displaying timer value
@label = UILabel.alloc.init
@label.frame = CGRectMake(20, 200, width - 20, 30)
@label.font = UIFont.fontWithName("AppleGothic",size:24)
@label.textAlignment = UITextAlignmentCenter
view.addSubview(@label)

Implements the action methods

We can define the startTimer and stopTimer methods as following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  def startTimer(sender)
    if @timer == nil
      @time  = 0.0
      @timer = NSTimer
           .scheduledTimerWithTimeInterval(0.1,
                                           target: self,
                                           selector: "timerHandler:",
                                           userInfo: nil,
                                           repeats: true)
    end
  end

  def stopTimer(sender)
    if @timer
      @timer.invalidate
      @timer = nil
    end
  end

  def timerHandler(userInfo)
    @time += 0.1
    string = sprintf("%.1f", @time)
    @label.text = string
  end

The above code creates and schedules a timer in startTimer that will execute the timerHandler method repetitively each 0.1 seconds. The timerHandler displays value into label, and stopTimer stops the timer by @timer.invalidate.

** IMPORTANT **:
Currently, if you use the data for a long time, you must keep as instance variables.
Refer: Runtime

Runs the StopWatch application

You may run the StopWatch application by rake command in Terminal.

1
2
3
4
5
6
7
8
9
10
$ rake
     Build ./build/iPhoneSimulator-5.1-Development
   Compile ./app/app_delegate.rb
    Create ./build/iPhoneSimulator-5.1-Development/StopWatch.app
      Link ./build/iPhoneSimulator-5.1-Development/StopWatch.app/StopWatch
    Create ./build/iPhoneSimulator-5.1-Development/StopWatch.app/Info.plist
    Create ./build/iPhoneSimulator-5.1-Development/StopWatch.app/PkgInfo
    Create ./build/iPhoneSimulator-5.1-Development/StopWatch.dSYM
  Simulate ./build/iPhoneSimulator-5.1-Development/StopWatch.app
(main)>>

StopWatch application

Appendix

There is full code which created in this article as following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class StopWatchViewController < UIViewController
  def viewDidLoad
    # retrive the UIView
    view = self.view
    # configure background color
    view.backgroundColor = UIColor.whiteColor

    # retrive the screen size
    frame = view.bounds
    height = frame.size.height
    width  = frame.size.width

    #--------------------
    # start button
    @start = UIButton.buttonWithType(UIButtonTypeRoundedRect)
    @start.frame = CGRectMake(0, 300, width/2 - 20, 30)
    @start.setTitle("start", forState: UIControlStateNormal)

    # connect an action method for start button
    @start.addTarget(self,
                     action: "startTimer:",
                     forControlEvents: UIControlEventTouchUpInside)

    view.addSubview(@start)

    #--------------------
    # stop button
    @stop = UIButton.buttonWithType(UIButtonTypeRoundedRect)
    @stop.frame = CGRectMake(width/2 + 20, 300, width/2 - 20, 30)
    @stop.setTitle("stop", forState: UIControlStateNormal)

    # connect an action method for stop button
    @stop.addTarget(self,
                    action: "stopTimer:",
                    forControlEvents: UIControlEventTouchUpInside)

    view.addSubview(@stop)

    #--------------------------
    # label for displaying timer value
    @label = UILabel.alloc.init
    @label.frame = CGRectMake(20, 200, width - 20, 30)
    @label.font = UIFont.fontWithName("AppleGothic",size:24)
    @label.textAlignment = UITextAlignmentCenter
    view.addSubview(@label)
  end

  def startTimer(sender)
    if @timer == nil
      @time  = 0.0
      @timer = NSTimer
           .scheduledTimerWithTimeInterval(0.1,
                                           target: self,
                                           selector: "timerHandler:",
                                           userInfo: nil,
                                           repeats: true)
    end
  end

  def stopTimer(sender)
    if @timer
      @timer.invalidate
      @timer = nil
    end
  end

  def timerHandler(userInfo)
    @time += 0.1
    string = sprintf("%.1f", @time)
    @label.text = string
  end
end

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

    # Sets the StopWatchViewController as rootViewController
    @window.rootViewController = StopWatchViewController.alloc.init

    @window.makeKeyAndVisible
    true
  end
end

Comments