New and Improved Motion Meetup

Gant and Matt are changing the format of Motion Meetup from an interview to a panel discussion plus the occasional interview. Here is the new panel:

image

Gant LabordeMatt GarrisonMark Rickert, and me

I’m sure the first meetup will be a work in progress, but we’re all trying to bring some RubyMotion information and entertainment to you each month.

It’s going to be at 3PM PST today, or you can catch it later. The special guest is Jack Watson-Hamblin. Please join us. The Google+ page is here.

If you missed the last issue, you can find it here: issue #19

Happy coding, Todd Werth (@twerth)

Articles, News, New Gems, and Blog Posts


Mar 24th, 2014 – “screencast – NSFetchedResultsController” by Jack Watson-Hamblin

Mar 24th, 2014 – “RubyMotion is Sexy” by Matt Brewer

Mar 23th, 2014 – “How to implement global hotkeys in your Mac OS X app using RubyMotion” by Elliott Draper

Mar 22th, 2014 – “How you doin’ RubyMotion” by Murtuza Kutub

Mar 21th, 2014 – “RubyMotion is not Rails” by Matt Brewer

Mar 21th, 2014 – “RubyMotion Preprocessor Code” by Jack Watson-Hamblin

Mar 20th, 2014 – “RubyMation, A Series of Animation Libraries for RubyMotion” by Multunus

Mar 10th, 2014 – “gem – yapper – RubyMotion ORM for YapDatabase” by Kareem Kouddous

Who knows – “Testing the presence of a UIAlertView in RubyMotion on iOS7” by Jaune Sarmiento

Motion Meetup Announcement

Today at 3pm PST, with a new panel of hosts and special guest Jack Watson-Hamblin

Please join us, or watch it later. The Google+ page is here

RubyMotion Tip of the Week


Enable User Interaction

You may have noticed that gestures don’t work on images (such as tap). They actually do, but userInteractionEnabled is false on UIImageViews by default. You simply need to turn on user interactions. The same is true for UILabel.

my_view = UIImageView.alloc.initWithFrame([[100,100],[100,100]])
self.view.addSubview(my_view)
my_view.userInteractionEnabled = true
recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action: 'some_method')
my_view.addGestureRecognizer(recognizer)

Other types of views, such as UIButtons, default to true, thus why gestures work for them.

If you use RMQ, you can do this:

rmq.append(UIImageView, :style_name).enable_interaction.on(:tap) do |sender|
  # do something
ended

iOS Marketing Tip of the Week by Mark Rickert


Internationalization (i18n) and localization (l10n) of your apps are a great way to reach a wider audience. The App Store is a global marketplace, so why not try and cater to as many as possible?

You may be asking, “What’s the difference between i18n and l10n?” I18n is the process of making your app localizeable. Theoretically you should only have to do this once. L10n is done multiple times, once for each locale you want to support.

The i18n process should include things like:

  1. Abstracting all text into an external file located in your /resources folder. Sugarcube has some abstractions that make this really easy.
  2. Making sure things like dates, times, currency values, sort order, etc. are formatted according to the user’sNSLocale.currentLocale
  3. Make sure to test languages other than your native tongue to see how they look. German words are on average_30% longer_ than English! Ensuring that very long text strings will fit and look good without truncation might take some time. Use UILabel‘s sizeToFit method or for even easier global styling, use RMQ’s UILabelStyler,

    Once you’ve internationalized your app, you do multiple localizations into other locales. This is mostly just string translation. You can get volunteers or use a service like PhraseApp to translate your app (who conveniently have a RubyMotion Gem).

    When you upload the new binary, Apple automatically detects the new languages your app is available in and denotes that in the left column of your app’s App Store page. I18n and l10n are certainly not easy, but the non-English speaking world will thank you for it.

CDQ News and Tips by Ken Miller


If you are using CDQ and you find that your UI sometimes pauses while your app is writing data, you might consider the popular “private writer” pattern. By default, CDQ will set up you with a single context right in the main UI thread. That’s the simplest to reason about, and is fine for many apps, so it’s the default, but if you are using a lot of data, Core Data provides a lot of flexibility. In this case, that means a special context which maintains its own captive thread, on which all writes can take place. By inserting this context into the chain below your main context, you can achieve perfect atomic consistency within your UI, while still deferring the actual physical writing to another thread, letting your main thread go about its business.

To use the pattern, instead of running cdq.setup as usual, run this:

cdq.contexts.new(NSPrivateQueueConcurrencyType) 
# private writer
cdq.contexts.new(NSMainQueueConcurrencyType) 
# UI context

This pushes a private queue context onto the stack first, then a main context on top of it, which is what your code will interact with directly. That’s all you have to change! cdq.save will correctly save both contexts in turn.

I’ll talk about even more advanced context arrangements in a future tip, but until then, here’s some background reading (which should also illustrate what CDQ is saving you from — see the section on Asynchronous Saving):

Multi-Context Core Data

Help support the Dispatch and signup over at MotionInMotion


MotionInMotion releases a new RubyMotion screencast each week. Here are some examples:

  • Episode 12 – Application URLs
  • Episode 11 – RMQ
  • Episode 10 – Teacup
  • Episode 9 – ProMotion + Formotion
  • Episode 7 – Working with the Camera

Sign up, it’s only $9AUD/month!

One more thing


The great folks over at JetBrains are sponsoring the RubyMotion #inspect Conference, send them your love.

image


If you have any tips, blog posts, or want to sponsor this newsletter, please send emails to todd@infinitered.com