I’m lazy – really lazy. So when I decided to create a free version of Converted, my first thought was: “How do I set this up so building the two versions and keeping them in sync requires no extra effort?”.

Since I’m no Xcode expert, it required some deliberation (and digging), but eventually I came up with a solution that fulfilled these requirements:

  • Both versions should be built from the exact same codebase; no branching or separate projects.
  • After the initial setup, building either version should be no more than a couple clicks; no edits whatsoever!

The solution hinges upon simply using 2 different Info.plist files. Apart from some Apple-specified keys that have to be set in each file, I also added (amongst others) a key for a boolean that controls the version (eg. XXIsLite). Within the code, the different functionality between the 2 versions is controlled by observing that boolean value.

Now normally, this solution is A Very Bad Idea™: a sneaky user of the trial version could just open up the bundle, change the key and gain access to the full version. On the iPhone however the bundles are signed, so this isn’t possible (I’m obviously discounting jailbroken iPhones that bypass the codesigning – anyone who goes to that much trouble to save a couple bucks is beyond help).

So here’s the process I followed, more or less:

  • In the ‘Groups & Files’ list, select your info dictionary file; by default, this is called ‘Info.plist’. Add a new line, set the key to something along the lines of ‘XXIsLite’ and the value to ‘NO’.
  • Again in the ‘Groups & Files’ list, expand the ‘Targets’ group. Right-click on the target that builds the app (in my case, Converted). Select ‘Duplicate’. Rename it if you like, eg. ‘Converted Lite’.
  • At this point it’s best to change the product name as well, so right-click on the new target and select ‘Get Info’. In the ‘Build’ tab, select ‘All Configurations’ from the configurations pull-down. Type ‘product name’ in the search box; change the ‘Product Name’ setting to something else, eg. Converted Lite.
  • Back in the ‘Groups & Files’ list, notice that Xcode has also duplicated your ‘Info.plist’ file and created ‘Info copy.plist’. Rename the new file to something else, if you like, such as ‘Lite-Info.plist’.
  • Setup the new info dictionary. At a minimum, you must change the bundle identifier to be different from the full version (com.codingcurious.ConvertedLite in my case) and set the value for the ‘XXIsLite’ key to ‘YES’.
  • Optionally, you can define a different home screen icon, a different display name or any other key-values you’d like to be different on the trial version.
  • Lastly, if you haven’t already, implement the code that will differentiate the trial version. Define certain “choke points” (the fewer the better) in your code where you check which version it is and modify or subtract certain features. For example, in the flip view Converted adds an additional “solicitation view” for the trial version that directs to the full version download page.

When you’re done, all you have to do to build either version is simply set the active target and build. This way, you can release updates for both the full and trial version with no extra effort at all!

Tip: when directing to the App Store, replace ‘itunes’ in the link with ‘phobos’; this will send the user directly to the App Store, without first launching Mobile Safari. For example,

http://itunes.apple.com/WebObjects/MZStore.woa/...

will first launch Mobile Safari and then redirect to the App Store, while

http://phobos.apple.com/WebObjects/MZStore.woa/...

will open the App Store immediately.

Posted on Thursday, January 29th, 20:12. Filed under: Converted, iPhone, Xcode

Despite the Palm Pre being the biggest news to come out of CES, I hadn’t really given it much attention, apart from the occasional headline or photo. I mean, it’s Palm, nothing good has come out from there in years!

And then I watched the CES Pre introduction video (here), and I have to say it: Wow. Sure, the device might be clunky, the battery life is uncertain, animations left a bit to be desired, and 3rd-party app development is something of a question mark, but what blew me away was how the Pre just nails the workflow. Everything is connected into one seamless experience, from messaging to the internet to notifications. Jumping from one activity to the next is effortless, and the information is always there.

It’s obvious that Palm went back to square one and threw away absolutely everything: not only their own technology, but also every preconception about how a mobile device should work. The Pre redefines the mobile workflow in such a way that it makes the iPhone look as archaic in design as the iPhone did its predecessors. This is the way a “personal digital assistant” should work!

It borrows heavily from the iPhone in some areas, like the device button layout, or the scrolling and zooming gestures, but then leaps forward and disposes of all the traditional mobile clutter. The gesture area, the ‘Card Deck’ concept, Synergy, and above all, the inobtrusive notification system shift the focus from managing applications to flowing through activities. In some cases during the demo, it wasn’t even clear where one application ended and another started: they were all seamlessly inter-connected.

Granted, these were just some of Palm’s first-party apps; it remains to be seen how well the third-party ones fit into the experience. But with Apple’s comparatively weak push notification system still MIA, Palm’s bold new design looks very promising indeed.
It also remains to be seen if Apple will be able to match or surpass the innovations found in the Pre; the iPhone is due for a refresh around the same time the Pre will be available. One thing’s for sure, however: competition is never a bad thing.

Will I buy a Pre? Probably not; it’s not even going to be available outside the US for quite a while anyway (due to EVDO), not to mention I’d be loath to go back to carrying a stand-alone iPod.

But it’s the first true innovation in the mobile space since Macworld 2007, and that’s exciting. Apple, your move.

Posted on Thursday, January 15th, 14:46. Filed under: iPhone, Mobile, News, Opinion

This was definitely a pleasant surprise: after only 5 days in review, I got the email saying that Converted has changed status to “Ready for Sale”. I was expecting it to take at least a couple of weeks, especially since the enrollment process was so frustratingly long.

As happy as I am, however, I do feel sorry for the person(s) at Apple working on a Sunday…

Posted on Monday, January 12th, 00:29. Filed under: Converted, iPhone, News

The thing that struck me most while working on the iPhone was how limited the resources actually are, something that isn’t (and shouldn’t be) obvious to the user. Going from the simulator to the actual device can be really jarring, because animations that seemed butter-smooth suddenly become a slideshow.

It can be very frustrating to go back to the code and try to figure out just what the issue is, so here are a few things to keep in mind while coding, performance-wise:

  • Transparencies are expensive; wherever possible, set views to be opaque, so there won’t be any wasted cycles refreshing the views underneath.
  • Always reuse cells; the docs seem to suggest that it’s simply a “good practice”, but it’s practically required. If you have a small table you might think it won’t matter to just allocate new cells, but once you start to scroll, the performance hit becomes obvious.
  • It’s better to customize cells by subclassing UITableViewCell rather than add subviews to the content view, especially if transparency is involved. I’m not entirely sure why this is the case, just that subclassing eked out a few extra frames during scrolling.
  • With normal-sized scroll views, loading subviews on-demand is actually worse. What is normal-sized? In my case, I tried up to 3200-by-460 and preloading the subviews yielded much smoother animations than any of the several load-on-demand methods I tried.

With most performance concerns, the common underlying issue is object allocation. Preloading definitely helps, but go too far and you start to bump your head against the memory ceiling. In the end, you want to balance object allocation and definitely use didReceiveMemoryWarning to clear out unused objects.

Overall however, I really liked working on the iPhone: it forces you to go back to the basics and come up with creative solutions: elegant coding is always better than the sledgehammer approach!

Posted on Saturday, January 10th, 18:11. Filed under: Cocoa, iPhone