Announcing: gs-apns, a new fork of the apns gem.

For the last year Geospike has been using jtv-apns, itself a fork of apns. Our needs have grown, and today I announce our own fork of the APNS gem, name ‘gs-apns’.

Gem on rubygems.

Code & docs on github.

The gs-apng gem continues the good work of James Pozdena and Paul Gebheim with some key enhancements including automatic message truncation, correct UTF-8 handling, rails-independent JSON encoding, full 256 byte message support, more failsafes and logging.

Read more…

A safer failsafe for beginBackgroundTaskWithExpirationHandler

As my brother succinctly put it “iOS likes to crash”. One such crash that can easily happen when you use background tasks is for your app to be killed for running the background task longer than the allotted time (generally 10 minutes).

The standard practice for avoiding this issue is to end the task you started with beginBackgroundTaskWithExpirationHandler in the expiration handler block of the same call. That works well, but there’s one catch. The UIBackgroundTaskIdentifier isn’t passed into that block, so you need to pass it through yourself. But what if some code modifies the variable you passed-in erroneously? If you are using a local variable, this isn’t a problem1 – but if your background task extends beyond one method it’s common to use a member variable, which could be accidentally modified.

And therein lies the danger. What if, despite all your very careful checking, that variable is modified. Now your failsafe won’t work correctly, and the app will crash. What’s worse, is it will crash in a totally random place. The crash logs give a very specific reason “App has active assertions beyond permitted time”, but don’t tell you exactly which LOC created the background task.

Here’s a better pattern. A safer failsafe if you will. Always declare the UIBackgroundTaskIdentifier as a local variable. End the task in the expiration handler using that local variable. After the task is created, set your member variable to equal the local variable for any additional additional processing (such ending the task naturally when it completes). Now the expiration handler is guaranteed to end the correct task, regardless of what else happens.

This pattern generates a bit of boilerplate code, and lets face it the more you copy and paste the less maintainable things get, and the more chance there is for error. So I’ve wrapped up this pattern into a simple utility class. The method is beginBackgroundTaskWithSafeExpirationHandler and it is designed to never crash with “active assertions beyond permitted time” no matter what you do. You can download the code from the gist.

Read more…

  1. blocks copy local variables on invocation, see the docs []

Changes to how Rails 3.2.13 and 4.0 encodes unicode in JSON

Heads up: how Rails handles unicode in JSON has changed in rails 3.2.13 and 4.0.

Previously unicode characters would be encoded with \u1234 notation. This encoding was actually a bit buggy, anything over two bytes (e.g. outside the Basic Multilingual Plane) would not render correctly1. With 3.2.13 and 4.0, Rails now just passes through UTF-8. That’s legal under the JSON spec2.

Does this change matter? Probably not, unless you interface with a buggy JSON parser that doesn’t support UTF-8. Also, if you’re using .length to get the bytesize of a JSON message you will now need to use .bytesize instead (previously length would have been equivalent, as it was an ASCII string).

If you need to get the old ascii encoding back, good news, you can! Replace your use of object.to_json with JSON.generate(object, :ascii_only => true). E.g.:

object = {:unicode => "I \u{1F49B} you"}
JSON.generate(object, :ascii_only => true)
 => "{"unicode":"I \\ud83d\\udc9b you"}"

Not only does this encode the unicode characters, it does it correctly even for the extended characters which the old Rails 3.2.12 to_json did not. Awesome!

This is useful for the odd time you have a service that can’t handle UTF-8 encoded JSON. But what if you don’t have control over the code that calls to_json?

Read more…

  1. Try: "\u{1F49B}".to_json on an old install if you dont’ believe me (.should == "\ud83d\udc9b"). []
  2. http://www.ietf.org/rfc/rfc4627.txt 3. Encoding: JSON text SHALL be encoded in Unicode. The default encoding is UTF-8. []

Email Marketing: The importance of the first sentance

Something a lot of people forget when designing newsletters or email marketing campaigns is that after the subject, the first line of text is the most important. That’s because, email clients like GMail and iOS Mail will display the first line of text right under the subject.

So you don’t want your email to read: “News Update from XYZ Widgets – [ Unsubscribe | Web Version ]” when it could read “News Update from XYZ Widgets – the new widget everyone is talking about”.

Simple solution: update your HTML template, and put a small 1-sentence summary of the topic at the top.

Here’s the before & after for Geospike:

Read more…

Good Unicode Table

For a long time I’ve yearned for a well presented Unicode table that gave simple ways to look up all the great glyphs that I need in Unicode ☄. If I wasn’t so busy I probably would have written my own ✈.

Well I’m pleased to say someone has created this and done a fine job of it too, unicode-table.com. You can search, view a beautiful large version of glyph, get unicode numbers and HTML codes. It’s also arranged in a geek-friendly bit-table. What more could you ask for? ❄☃

iOS support would be nice I guess – though at least it’s still usable (and works with the iOS clipboard ១ – no mean feat).

Booking Train Tickets in China: Now Even Less Painful

Booking Train Tickets in China has always been pretty decent: there are a bunch of official ticket agents around suburbs and towns, changing ¥5 per ticket as a fee but allowing you to book from the clamness of your own street instead of the crazyness in the station.

Recently it got even better. You can now see availability online, and book tickets at www.12306.cn (if you can read Chinese and have a Chinese credit card, or a friend who can help). Tickets booked in this way can be collected at the ticket agents (for the same ¥5 fee), or at the station (for free). They can also be refunded online, until you collect them (after which you can refund them in the usual way).

Read more…

Bug Report: Build packs on Heroku are not fully applied if you specify the BUILDPACK_URL after creation

This is an issue I am having when trying to use a custom buildpack with Heroku. The intent of the buildpack is to update the version of ImageMagick on the heroku dyno which is over 2 years old.

Read more…

The Problem with Bitcoin

I love the idea of bitcoin. Well, I love the idea of a crypto currency with zero transaction fees, and no government intervention. But the problem I see with Bitcoin is demand.

Like fiat money, Bitcoins are another “make believe” money that has value only because we say it does. Many argue it is superior to government issued fiat money as the its money supply is deterministic and slows in growth over time (rather than at the whims of the government of the day). Read more…

Add This

‘Add This’ gives you an easy way to add social media buttons to your site in a “consistent” manner. No need to add a bazillion js includes for every site you want to support.

The catch? They track your users. You can’t opt-out your entire site.

It sure makes those buttons easy to add, but yeah that’s the price: someone will be tracking your users on your site. Incidentally, twitter is also doing this now with its tweet button, but you can opt-out on a site-level (which is good!).

The Problem with “Sponsored” Tweets

is that you can be having a conversation, and some bozo with lots of money can just pay to have his voice heard above all the others, regardless of organic social ranking (based on likes/retweets/etc). Read more…