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:
Gant Laborde, Matt Garrison, Mark 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:
- Abstracting all text into an external file located in your
/resources
folder. Sugarcube has some abstractions that make this really easy. - Making sure things like dates, times, currency values, sort order, etc. are formatted according to the user’s
NSLocale.currentLocale
- 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
‘ssizeToFit
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):
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.
If you have any tips, blog posts, or want to sponsor this newsletter, please send emails to todd@infinitered.com