New and Improved Motion Meetup
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.
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 23th, 2014 – “How to implement global hotkeys in your Mac OS X app using RubyMotion” by Elliott Draper
Mar 20th, 2014 – “RubyMation, A Series of Animation Libraries for RubyMotion” by Multunus
Motion Meetup Announcement
Today at 3pm PST, with a new panel of hosts and special guest Jack Watson-Hamblin
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
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
/resourcesfolder. 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
- 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
sizeToFitmethod 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
- Episode 12 – Application URLs
- Episode 11 – RMQ
- Episode 10 – Teacup
- Episode 9 – ProMotion + Formotion
- Episode 7 – Working with the Camera
One more thing
If you have any tips, blog posts, or want to sponsor this newsletter, please send emails to email@example.com