Top 3 features you need to know about

Writing Objective-C-looking Ruby is just a complicated way to write your apps. In this section, we're going to cover some aspects that put the Universe back in order, where the features of RubyMotion allow you to make your app clear and actually fun.

Debugging

No one wants to write broken code, but it's inevitable. Debugging is as important as programming itself, especially in large and complicated applications that need advanced inspection and care to discern.

Fortunately, RubyMotion takes debugging your applications seriously and provides benefits that bring your interaction to new heights. Many features provided in RubyMotion debugging are either difficult or impossible to do with traditional iOS development tools.

Let's get started! Let's begin by running our Hello World application as normal. Once the application has loaded in the simulator, you may notice the command line is available to receive the input. This command line is known as the REPL. If you know anything about Rails, this strongly feels like the Rails console or even pry. From this REPL we can directly communicate to the running application.

Sounds too good to be true? Let's play around with Hello World for a moment and see. One of the benefits of writing excellent tests is that it goes hand in hand with good REPL play. Though it would be best to break references into several commands, I'll be concatenating some of our test code into fewer commands, for directness. Type the following into the REPL:

(main)> @rc = UIApplication.sharedApplication.windows[0].rootViewController
(main)> @rc.view.backgroundColor = UIColor.redColor

After typing the long statement mentioned in the preceding command, you see the background of the currently running Hello World application turn bright red! Via the REPL, we were able to directly modify our application without modifying any of the application code. This is great for working directly with the application while it is live!

Why stop there? Let's change the text, too! Type the following into the REPL:

(main)> @hello_label = @rc.instance_variable_get("@label") 
(main)> @hello_label.text = "Hello Human!"

Well, that was almost cool, but though your application's label text has changed, you can see it no longer fits in the previous frame settings and has a white background. Now you understand the visual context of a frame. Let's use some of our code that we used in the Quick start – creating your first application section to set the size and color.

The following two lines should do the trick:

(main)> @hello_label.sizeToFit
(main)> @hello_label.backgroundColor = UIColor.clearColor

Your result will end up something like this:

Debugging

There it is! Now you were able to instantaneously modify the application and see the results. Your application looks tremendously different, and all the changes we've identified will be wiped clean as soon as we kill the simulation or exit the REPL. This gives us the ability to experiment in the REPL and then make changes as needed.

As impressed as you may feel, this sure was a lot of typing just to identify different aspects of the application. The good news is that for graphical assets we have a shortcut! Start up your Hello World application again, and let's see it in action.

Press the command key on your keyboard and hover over the application. You'll notice a red outline around view elements as your REPL adjusts. By clicking on any element your REPL will select it. The easiest example is to click on the view, which will make your REPL look something like the one shown in the following screenshot, with likely a different memory address:

Debugging

The REPL is now selecting the UIView! Let's have a look around. Go ahead and type self.subviews into the REPL. You'll be presented with the only subview, which is our "Hello World" label. Type self.superview and you'll be presented with the instance of the window that contains us. So, by just command-clicking the visual element, you immediately jump to what was originally @rc.view. This is a great shortcut whenever you would like to start at any visual asset of your application.

The REPL, such as the Rails console, can also be used to do exploratory programming on base Ruby objects. You can use it to help you understand the hierarchy of the classes and run functions that have nothing to do with the current application.

It's important to note that all RubyMotion objects are on top of Objective-C, objects. At any moment you may be able to take your RubyMotion object and tap into Objective-C, or take your Objective-C code and simplify it with some yummy Ruby! While at the REPL, type the following code:

(main)> @array = []
(main)> @array.class.ancestors

This yields the following result:

=> [Array, NSMutableArray, NSArray, Enumerable, NSObject, Kernel]

As you can see, your Ruby array is sitting on top of Objective-C, the original structure of NSMutableArray. No explicit declaration of the NSMutableArray object was needed, and the objects can be instantiated all in the same clear line. If you're familiar with Objective-C, you will see why this is such a benefit. When you look up the iOS code examples, there's usually a large amount of refactoring you can do to create clean idiomatic Ruby.

If you're interested in more advanced debugging, you can always invoke the RubyMotion debugger that is based on the GDB. To do this, you can run your application with the flag of debug=1. The command will look something like this:

$ rake debug=1

You can even use this to debug switch, while the application is running on your device. Lessons on how to handle the GDB are beyond the starter scope of this book. Laurent Sansonetti wrote an excellent article on how to utilize this aspect of RubyMotion, which can be found at http://www.rubymotion.com/developer-center/articles/debugging/.

Implementing a Gem

As previously mentioned, one of the most powerful aspects of Ruby is the ability to utilize the wide array of open source code known as Gems. Up until now we've written all the code from scratch, but now we can import thousands of lines of code that will help us clean up our application, with only a modicum of effort. There are a few ways to manage Gems, but we'll be using Bundler, a Ruby dependency manager.

Step 0

First, we'll install Bundler, if you don't already have it. If you've got a very tricky version manager, or you're just plain 100 percent new to bundling, you'll need to take a moment to install Bundler. This is a one-time (sometimes once per project) task. Just run the following command to install:

$ gem install bundler

Note

You may require sudo depending on you setup and system.

Step 1

Now that we have Bundler, we'll be able to handle everything from a clean Gem file. The first thing we need to do is add that Gem file. Bundler has a short and sweet command to help us do so. Enter the following command:

$ bundle init

This will automatically generate a file called Gemfile, and set the source to look at rubygems.org.

Step 2

Open this file in your preferred editor, and modify it properly so it looks like the following:

Step 2

We've told our Gemfile that we'll be making use of four Gems listed on lines 4 – 7.

Note

Three of these Gems (teacup, sugarcube, and sweettea) are managed by a single developer named Colin, from the RubyMotion Group. sweettea actually depends on the other two (teacup and sugarcube) to work. Gems will pull in its dependent gems as needed, so it's actually redundant that we have it listed here in our Gemfile. They should still be listed here because we intend to use them regardless of sweettea, and utilizing Gemfile allows us to micromanage specific versions for each of these Gems, should we need it. Just keep in mind a new version of one Gem that depends on the other might have a newer Gem dependency than you're providing, so version wisely.

Step 3

Edit your Rakefile by adding the following lines 4 and 5, so your file will look similar to the following:

Step 3

Line 4 tells the Rakefile to require the Bundler Gem functionality, and the following line 5 tells RubyMotion to include the Gems listed in our Gemfile, using Bundler to do so. Though there are other ways to handle Gems, I strongly recommend that you utilize this method! Now your code can be given directly to another developer with all Gem dependencies listed in a separate file, while the application automatically compiles these dependencies for you!

Upon editing your Gemfile, it's good to run Bundler to validate your dependencies and their installation.

$ bundle install

Now when you run your application via some command, such as the following:

$ rake retina=3.5

Your application will retrieve and compile all the Gem dependencies for you! You might hear your computer's processor fan finally kick into action, and this may take a while on your first execution of the application. But fear not, the process will not take as long on subsequent compilations, unless the /build folder is cleared out.

Note

The time saving you get from the /build folder keeps us sane, but just like with any compiled application, cached builds can cause oddities. Clearing the /build folder may fix issues that seem to illogically persist in your application. Often, assets in the resource folder can be passed over or left inside an app regardless of your latest code base. If you are having any resource complications, I recommend running a clean and starting with a new run of the application. The rake clean command is just that:

$ rake clean

Utilizing Gems

Ok, so we've included those Gems listed, but we're not using them. Let's play with our Hello World application from earlier on so we can see the benefits! We're going to add some small functionality to our app to change the background colors while we refactor the application.

No tests will be written for this section since the Gems we're going to use all have their own tests. We will not be straying into new functionality, just adding bells and whistles.

Note

Gem Awesome Print: This is a RubyMotion Gem that prints Ruby objects with color and exposes internal structure via clear multiline indentation.

Now let's add some Awesome! Remember how we used puts and p to write variables? Well, there's a fancier version that a lot of Rails developers are familiar with, called Awesome Print. Fortunately, there's a port for RubyMotion that we've included. The best way to see the benefit of this is to see it in action. Let's add an array to the top of the viewDidLoad method from our HelloWorldController class.

Add these lines inside the viewDidLoad method:

@colors = [UIColor.whiteColor, UIColor.redColor]
ap @colors

Now when you run your application you'll receive a very clear multiline representation of your created array! That is much fancier and clearer than regular printing. Awesome Print can truly save you some significant time when projects get thick:

Utilizing Gems

Awesome Print has lots more tricks up its sleeve. To see more options, review the Gem's source page at https://github.com/michaeldv/awesome_print_motion.

Note

Gem SugarCube: SugarCube is a RubyMotion Gem that helps convert verbose iOS objects into more idiomatic Ruby brevity, and therefore more enjoyable syntax.

Now let's add some sugar! Remember that array of colors? Rather than using the verbose UIColor, we can shortcut them with SugarCube. This means we can convert the two colors like so:

  • UIColor.whiteColor => :white.uicolor
  • UIColor.redColor => :red.uicolor

With SugarCube you can represent colors in a vast amount of ways, including arrays, hex, and images! We'll stick with the preceding method, and even add a few. Let's adjust the @color array to be something like the following:

@colors = [:white.uicolor, :red.uicolor, :yellow.uicolor, :blue.uicolor]

Now that we've got an array of colors, let's have some fun with them. We'll use one more aspect of SugarCube before moving on. Let's use SugarCube's NSTimer wrapper to change the background colors of our view.

We can easily create a code block that executes continuously with little effort. Add the following code under your @colors array:

1.second.every do
    view.backgroundColor = @colors.sample
end

The preceding code executes the block every second. The Ruby code inside will randomly grab a single color from the array and assign it as the background color of the view. Unless you suffer from epilepsy, you'll enjoy running your application now!

For reference, your code base should look similar to the following:

Utilizing Gems

This was only a small taste of SugarCube's functionality. There's a vast amount of code to be explored on the Gem's source page at https://github.com/rubymotion/sugarcube.

Note

Gem Teacup: A CSS-ish DSL for building interfaces programmatically.

Using Teacup we can help separate some of this design and make our code look nice and clean!

Let's start by creating our styles folder under our app folder. In that styles folder let's create a file named main_style.rb.

Tip

Adding styles under the app folder will make sure your styles are picked up and used. If you want to keep some styles outside of the app folder, you'd have to add additional code to your Rakefile to let your app know it exists!

Before we start putting content in that style, let's get our app ready to use it! We'll add a bunch of code to the top of our controller and remove the styling and positioning code from the bottom. The end result will look like so:

Utilizing Gems

On line 2, we've added the reference to the stylesheet. Lines 4 – 6 tell the view to add our label to the view, but to style it with the:hello_label style (which we haven't written yet). We've renamed viewDidLoad to layoutDidLoad, which is called when the Teacup is done with viewDidLoad. Lastly, we removed all the code for the @label that existed.

Now let's style the label in our stylesheet we created. We can write hundreds of lines styling our label, and our application would remain the same size, so the benefits are obvious! Additionally, we're only dealing with one label at this time. Imagine how much reusability styles could afford us.

Now modify your main_style.rb stylesheet to look like the following:

Utilizing Gems

Now, as you can guess, the stylesheet is created for :main on line 1. We start a specific style on line 3, which we will have applied to our label. From there it's very straightforward! We set the text, width, height, center, and even set the background color so it's not an ugly block.

Running your application will yield the stylesheet in use via Teacup!

To see more examples of things you can do, and the advanced uses of Teacup, you can read the documentation on the Gem's page at https://github.com/rubymotion/teacup.

Note

Gem SweetTea: A RubyMotion Gem, which allows you to tightly integrate your SugarCube syntax inside Teacup styles via handlers.

There are a few annoyances in our stylesheet we just created. Firstly, we had to set the width and height, additionally we had to use that ugly UIColor native object again. Wouldn't it be great if we were able to place our SugarCube code inside? Fortunately, we have SweetTea in place! Let's refactor our previous stylesheet to look like this:

Utilizing Gems

We were able to remove the width/height lines and bring back our old friend sizeToFit! Additionally, we set the backgroundColor attribute to the:clear symbol with .uicolor implied, and we were able to set the center using a very readable 50 percent indicator of our super view.

To examine the source or other shortcuts provided by SweetTea, you can see all the details here on the Gem's source page https://github.com/colinta/sweettea.

The final code for this section can be found online at https://github.com/GantMan/HelloWorld/tree/gem_refactor.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset