Moving sites
I’ve moved over to blogging about mobile development and iOS over at http://scottpersinger.com. Come check it out.
Drawing Unicode text with Core Graphics on the iPhone/iPad
Drawing text using Core Graphics seems so simple, just use the good old CGContextShowText or CGContextShowTextAtPoint function right?
Unfortunately these functions do have support for drawing Unicode text. You have to convert your text to ASCII just to draw it.
Fortunately, its not really that hard to draw Unicode text. I’ve extracted some code from our Showyou app that does just that:
NSMutableAttributedString *aStr = [NSMutableAttributedString attributedStringWithString:@"some UTF8 text"];
CGContextSetRGBFillColor(context,1.0,1.0,1.0,1.0);
[aStr setTextColor:[UIColor whiteColor]];
CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)aStr);
CGContextSetTextPosition(context, x, y);
CGContextSaveGState(context);
CGContextClipToRect(context, clipRect); // if you want to clip the drawing
CTLineDraw(line, context);
CFRelease(line);
CGContextRestoreGState(context);
Simple!
The Genius of Apple – Users First
There are a lot of what I believe are misconceptions in the developer community about how Apple runs its mobile (iOS) business. I know, because I used to hold and promote many of these ideas myself. I think a lot of these ideas are natural responses to Apple’s approach to the market, but I also think a lot of people miss what’s really going on.
The basic misconception is that Apple makes it hard on developers because they don’t care. The complaints are legion:
- iOS programming is difficult, and Apple doesn’t care
- Android has garbage collection, why can’t iOS?
- Apple hates the web, wants everyone locked into their proprietary tech
- App Store approval is a big road-block that exists only to service Apple’s need for dictatorial control
The most recent example of this complaint came in a “Letter to Steve Jobs” blog post over at TechCrunch. There’s nothing wrong with asking for garbage collection, but there is something wrong with asking for it without realizing why it’s missing.
A bit of history
I have been doing 95% web development for the last 9 years, right up until December 2010. Last spring I helped my company develop our first iPhone app, Vodpod for iPhone. I probably spent about 4 teeth-gnashing weeks doing iOS development. I came away with a pretty dim view of the iOS platform from a developer’s perspective.
But then last December my company embarked on the development of our new app Showyou. This was a brand new app, and a big team effort. We were making a strategic commitment to the iOS platform way beyond our previous efforts.
And so I spent another 6 weeks clawing up the iOS learning curve. Coming after doing Ruby on Rails development for 4 years, writing Objective-C for iOS seemed primitive and horrible. Wrestling with memory management, the XCode environment, UIKit and its notorious table views, the static/dynamic language limbo that is objective-c, etc… I was around in the 90′s when NextStep was introduced, and the 20 year old lineage of iOS is right there in your face.
But then, finally, I got over the beginner’s learning curve. And then once I finally got the “What” of iOS development, I started to feel like I was finally understanding the “Why”.
I think the basic “Why” of iOS development goes back to core Apple philosophy: users come first. I want to explore some of the implications of that philosophy on the development process.
Embrace the Constraints
Rock music is an incredible limited art form: 4/4 time signatures, 4 standard instruments, 1-4-5 chord progressions. And yet within these very narrow constraints blossoms a huge range of incredible music. I think we can make an analogy between artistic constraints and the constraints of mobile device app development.
The fact is, the iPhone and iPad are underpowered computers. They have limited storage, limited memory, (relatively) slow processors, slow network connections, and most importantly, small screens. And thus to make a great application user experience for these devices, you have to design with all those limitations in mind.
And this I think is where the genius of Apple comes in. They aren’t trying to hide those limitations from the developer. On the contrary, they are constantly exhorting you to understand and embrace those limitations. “Design for one task at a time”, “make buttons easy to press”, “use animations to show the transition from one view to the next”, “be miserly with memory”, “keep your interface responsive”, and so on. Their message is simple: Our top priority is to provide a great end-user experience, not to make your life as a developer easy. It’s not to say that they don’t want it to be easy to develop applications. Clearly they have invested heavily in documentation, tutorials, the XCode toolset, the simulator, and so on. But rather than focus on making it simple and easy for you to create a simple – and probably poor – application, instead they have focussed on helping you make a great application.
The missing GC is a feature
And thus to garbage collection. It’s great to never have to worry about memory allocation and deallocation. Trust me, I’ve been using Ruby for 5 years, and Java for 7 before that. But in a great mobile app, on these limited devices, I think its reasonable to predict that a garbage collector is not going to work as well as managing memory yourself. And in the overall scheme of app development, its not that big a hit. I’d guestimate that we didn’t spend more than 5% of our development time worrying about memory management. And in my mind we spent a lot of time worrying about memory! Our 2D grid of video thumbnails is pretty huge. In the early incarnations we tried to draw the grid as one big view. No dice. Just trying to draw the tiled background image caused the device to crash. So I spent a lot of time worrying about when various views would get deallocated.
I think its totally reasonable to debate whether or not a GC should be included in the mobile toolkit. Maybe Android has proved that it can be done without hurting the user experience. But I think if you come to understand Apple’s philosophy towards their platform, then you will understand why they’ve excluded GC from their mobile devices.
The App Store is for users
I have had a strong feelings about the App Store process for a long time. I am a huge fan of the open web. I believe freedom of choice, and a level playing field. And I think the openness of the web has been critical to its success. So on principle I am not a big fan of the walled garden that is the App Store.
But I believe you can start with the “users first” principle and arrive at the App Store and its process. We can argue about the particulars, but I think you have to admit that the App Store provides an amazing channel for developers to reach a worldwide audience of paying customers. You can say that all of that is doable on the web at large, but I can argue that every rule in the App Store contributes to making it a more effective developer->user market than the open web.
And I will liken the App Store to the approach Apple has taken with the development environment: the App Store is oriented towards exposing and supporting great apps, not just apps in general. It’s a philosophy that says “What users need is 50 great apps, not 10,000 average apps”. We can argue about whether that is the best approach for end users, but don’t argue that the process isn’t good for the average developer, because that isn’t the priority.
Apple and the web
I have come around to disagree with the notion that “Apple hates the web.” I do however, tend to think that Apple either doesn’t completely “grock” the web, or maybe just doesn’t appreciate its strengths. (Q: why can’t mobile Safari cache a web page?) I do think they had great insight to realize that existing web sites were not going to provide a good experience to users on mobile devices. No matter the technology, I’ve come to believe that you have to build specifically for the mobile device. Expecting to shrink down desktop-targeted web pages has clearly failed as a strategy for mobile apps.
This is not to say that we won’t see great HTML5 mobile apps – I believe that we will. But the great apps will be designed for mobile devices. This is another example where you can derive the Apple position just as easily from “users first, embrace the device” as from the notion that Apple hates the web.
The Philosophy
Apple’s approach reminds me of David Heinemeier Hanssons’s theory of opinionated software. Apple’s products, including their processes, have a distinct point of view. I think a large part of that point of view boils down to:
- Users come first
- Simplicity is everything
- Embrace the constraints of your device
For developers, this means more work. Apple is challenging you to work harder to build better apps for end users. Making your life easier is not their #1 concern (it’s probably not even #2 or #3). It can be painful, but the end users will tell you that its worth it.
Just like religion, there’s no point in arguing with someone over their philosophy – you either agree or you don’t. And if you want to play in the Apple ecosystem, better to spend more time understanding that philosophy than complaining about it.
iOS Trick: Add padding to a UITextField
Subclass UITextField and override this function:
- (CGRect)textRectForBounds:(CGRect)bounds {
return CGRectMake(bounds.origin.x + 10, bounds.origin.y + 8,
bounds.size.width - 20, bounds.size.height - 16);
}
- (CGRect)editingRectForBounds:(CGRect)bounds {
return [self textRectForBounds:bounds];
}
Good practice is have your own text field class with “paddingX” and “paddingY” properties.
Plugging memory leaks in your iPhone/iPad app
I’ve been doing a lot of iOS development recently, and just got around to looking at all the memory leaks in my app! Ah, quite the education.
Turns out XCode has some awesome tools for tracking down memory leaks. Today I’m gonna give a short tutorial on using Instruments to find and fix your leaks.
Just fire up XCode with your project, build, then select “Run -> Run with Performance Tool -> Leaks”. This will fire up the Instruments app (a separate app) and automatically create a “Leaks” instrument, and it will start your app in the simulator.
Run your app for a bit, then switch over to the Instruments page and click the “Record” button to stop recording.
Now select the “Leaks” instrument, and you’ll get a display like this:

The main view is the table towards the bottom. I find the “Leaked Blocks” view the most helpful.
That table will list all the leaked objects from your app. Now “leaked” just means that there’s no more references in your app to a particular item on the heap, but the reference count for that item is greater than 0 so the system can’t remove it.
In the example above, we can see very simply that my FeedViewController is leaking an instance of UIBarButtonItem.
Now here’s where it gets interesting. Click that little arrow in the Address column of the table and you get a display like this:

This shows the reference count history for that object. The first row shows that we alloc’d the button in the FeedViewController. The next two rows are down in the system, a “retain” followed by a “release”. Presumably this where the UINavigationBar retained the button while it was showing it.
All reference counts for your objects should start at 1 after alloc, and then eventually get back to 0. When they don’t is when you have a leak. The ref counting is equalized in the system, so we can infer from the history that we’re missing a “release” in FeedViewController. And sure enough, here’s the code:
self.navigationItem.rightBarButtonItem =
[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSearch...];
Classic. Remember “Alloc” always sets the ref count to 1, so you need either a release or an autorelease to decrement it. The easiest fix here is just this:
self.navigationItem.rightBarButtonItem =
[[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSearch...] autorelease];
Rebuild, run with Leaks, and sure enough the leak is gone. After working with this tool you start to understand the patterns indicative of typical errors. Can you guess the problem just by looking at this ref count history?

In this case we are alloc’ing the object and assigning it to a “retain” property. You can see the ‘alloc’ and the ‘retain’ from the property. And we can see that we called ‘autorelease’ after the alloc, and indeed the autorelease pool called ‘release’ later. So what’s missing? Hmm…seems like their should be a ‘release’ to go with the ‘retain’ from the property setXXX. And indeed, when I checked out the source, we were simply missing the ‘dealloc’ function altogether. The same thing would happen if you didn’t use ‘self.property = nil’ or ‘[self.property release]‘.
I’ve worked out some good rules-of-thumb when using the Leaks tool:
- Test small sections of code one at a time. This makes things much easier.
- In the Leaked Blocks list, look for the top-most objects first. Often you’ll find that object B was reported leaked, but that happened because object A which contains B was itself leaked. So always start at the top of the object graph.
- Click into the history of a leaked object and carefully match reference count increments to decrements. This will usually show you where the problem is.
Using sed on the mysql slow query log
Sed is one of those great UNIX utilities which is well impenetrable enough that I have to lookup examples every time I want to do something with it.
But, for dipping into huge log files it’s great. Here’s a simple command for grabbing all the lines in a log file after the appearance of some text. In this case I’m looking for all lines from my Mysql slow query log after a given date:
cat db1-slow.log | sed -n '/Time: 081026/,$ s/.*/&/p' > slow-oct26.log
The -n option to sed turns off line echo, then the /p command enables printing matching lines. The regexp supplied before the s/../p part makes that command take effect after that pattern is matched.
Enable slow query log on running Mysql 5.1
Here’s a tip for dynamically enabling the slow query log on a running Mysql server without having to restart the server. Remember to go set the config settings in my.cnf, but this enables the log without you having to restart the server:
--> go touch /var/lib/mysql/slow_queries.log and make it owned by mysql
set @@long_query_time=1;
set GLOBAL slow_query_log_file='/var/lib/mysql/slow_queries.log';
set GLOBAL slow_query_log=1;
You’re welcome.
IE9 support for Vodpod.com
We’ve added support for a bunch of new Internet Explorer 9 features around “site pinning”. You can read all about them on this post about Vodpod support for IE9 pinning.
Vodpod on Android
My name’s Kyle, and one of my projects at Vodpod has been building an Android app for Vodpod.com. I’d like to talk briefly about what sort of challenges we had to solve in making the app, and hopefully give other developers a leg up on the process.
Architecture
The app comprises a constellation of activities, including a home-screen launcher, two services, classes representing each type of data provided by the API (Video, User, Collection, etc.), a singleton client for interacting with the API, an SQLite-backed content provider, and a few helper classes for formatting.
Most of the activities are straightforward: they load an XML view, pull data from the API in an AsyncTask, and when the network request is done, populate the view with the appropriate information. For our list views, we use the CWAC Thumbnail library to load thumbnails on demand.
The largest service handles several tasks, including synchronizing some preference data and uploading files to the service. We use the Apache Commons http client with mime4j and multipart for all requests.
The second, smaller service is purely for feed synchronization. It downloads new feed items and populates our content provider, issuing notifications as necessary.
The feed view is different than most of our network-backed views. It links directly to our feed content provider, which lets us store tens of thousands of feed items and scroll through them at incredible speed.
Finally, all the network requests share common paths, serialization, and response validation code. A singleton client class handles authentication and provides nicely typed methods for retrieving lists of videos, feed items, etc. Each NewsFeedItem, Video, Comment, and so forth are responsible for populating themselves recursively from a JSONObject. They also persist themselves to ContentValues objects for serialization. Instantiating extra objects increases parse time, but simplifies error handling, data lookup, and cuts down on memory footprint.
Storage
The Vodpod data model is a deeply nested directed graph of objects, which doesn’t lend itself well to serialization in row-column oriented datastores. We investigated using db4o as an object store.
Db4o is a fantastic database with excellent capabilities, but there are caveats. First, even the base db4o jar increases build and install times by several seconds, which lengthens development cycles. Second, Dalvik doesn’t always play nicely with the db4o serializer on third-party classes. For example, the Joda DateTime class can’t be deserialized correctly. Your only choices are extensive subclassing (which involves awkward casts on basically every operation) or implementing custom serializers.
Eventually, we abandoned Db4o in favor of an SQLite-backed content provider. The Android API is designed to support this storage model out of the box, and it’s extremely fast. The drawback, of course, is that our nested data needs to be denormalized into a table. We pre-render as much content as possible to save processing during display. For example, we colorize usernames and generate appropriate titles for each feed item before storage.
Latency is Key
We originally wanted to deliver much of vodpod.com as a mobile-optimized HTML5 web app. That approach would have let us share the vodpod experience across all platforms, instead of separate development tracks for iPhone and Android. We built a pared-down version of the video page for mobile browsers, and made some interesting discoveries: high latency kills the experience.
When you’re on your phone, waiting two to three seconds for a page to load over wifi is obnoxious. It breaks the applications “flow” and makes interacting with the app more like work. Over a 3g network the effect is stronger. Near-instant responses dramatically improve the subjective feeling of the application.
We tried to cut out as much fat as possible from the video page, but were still not able to offer a reasonable load time. In contrast, our mobile apps use a combination of caching and efficient API requests to offer pages in under 50 milliseconds, with videos loading in 0.5 to 4 seconds depending on payload. The performance difference (along with the advanced lifecycle management offered by the android platform) is a good reason to spend the time writing a native app.
Optimization
Declare everything you can final. What isn’t final you should be re-using. Try to avoid object instantiation overhead, since you pay a price in creation *and* in GC sweeps. Android provides plenty of opportunities to re-use objects: for example, in ListViews, views that scroll off the top of the screen can be re-used for the incoming items at the bottom.
Cache everything. Don’t create a new handler subclass for each button; use a single handler and store the data to be acted on in a tag. And recognize that *how* the user interacts with the app influences performance more than raw algorithmic complexity: it can be more efficient to parse and create a new intent when a button is pressed than to precompute and store that intent ahead of time.
Locking and thread management in Java are nontrivial. Inevitably you’ll find yourself accepting that a probabilistically successful implementation is significantly easier than reasoning about a correct one. With limited time, this tradeoff can be worthwhile.
Don’t sweat the small stuff: when one of your requests involves 100ms of network time, an extra 20ms of parsing doesn’t really matter. But do it in the background. Progressive enhancement is worth it: grab the basic metadata first, then the images, then the video. Above all, let the UI remain responsive.
Accept that efficent code is more complex. Managing a service, multiple threads, observer callbacks, DB transactions, and view refreshing means more time spent debugging and implementing simple features. It’s only worth doing for cases where performance (or in our case, offline storage) is critical.
Prioritizing
We’re only six people total, and provide content to something like 10 million unique visitors per month. I’m the sole Android and API developer, and about half of my time goes to building the app.
It *is* possible to build a functional app on limited dev time. But that means focusing carefully on getting the most out of every hour of development. We’ve left graphical glitches, stutters, crashes, and obtuse error messages unfixed simply because it takes so much time to track them down.
Instead, we’ve been focusing on implementing new features and critical fixes. I’m normally a perfectionist about this stuff, but it’s better, I think, to offer a feature which is broken 10% of the time than to not have it available at all.
Release strategy
I’ve been working with Lighthouse on this project, which helps a lot with planning improvements. We started out with monolithic releases including a huge set of of changes. Lately, though, I’ve been grouping our to-do items into clusters of five or ten issues around a specific feature, and trying to complete a release in a week to 10 days.
For instance, our next release includes numerous adjustments to the video page layout (margins, colors, and thumbnail sizes), a link to the original video page, and some new features such as user profiles and following. It also includes a couple of small bugfixes that I knew were easily solved. Trickier bugs, like “Uploader locks up in HTTPClient during intermittent 3g connectivity on large uploads” are deferred because they are so difficult to reproduce and analyze.
Android makes it easy to iterate rapidly–it takes only 10 minutes to go from finished code to release in the market. I’ve found that releasing small sets of changes more frequently makes it easier to set deadlines and stay motivated.
Resources for developers
The Android SDK docs are pretty darn good, but there are still undocumented corners. To fill in the gaps, I refer often to the included API demos in android/platforms/*/samples/ApiDemos. #android-dev on Freenode can be hit-or-miss, but the folks there tend to have that elusive best-practices knowledge. “Should I rebind my service in onResume or onStart?” They know.
Finally, StackOverflow has a wealth of Android Q&A. Unfortunately, finding one that pertains to your particular problem can be difficult.
Vodpod for Android is now available in the Android Market.
Vodpod on iPhone
Hi, I’m Ali. I’ve been interning at Vodpod for the past two months and it’s been great. Here is a bit of information on what I’ve been working on with my time here.
When I came to Vodpod in the beginning of the summer, we were trying to think about how to expand our mobile offerings. It was pretty obvious we wanted mobile applications for the two big growth platforms, iPhone and Android, but we realized that would be a huge challenge. Most of Vodpod’s videos are based on Adobe’s Flash plugin, which has advantages and disadvantages. A disadvantage would be that Flash videos don’t play on the iPhone due to Apple’s decisions for the platform, but we would obviously want to give the user the ability to play videos on his or her phone if they desired.
That took us to the drawing board where we decided that we would just let the user watch a video on the original host site. We did some tests and found out a large percentage of videos actually worked on their original sites because of HTML5 and some fancy browser detection that was unique to each host site. It was a pretty elegant fix and gave the best experience to all our users. After personally using the application for weeks, I have found that almost all of the videos I tend to watch in line at the coffee shop or waiting for the MUNI play seamlessly from within the application.
Development was a hard-pressed in the beginning because of our decision to use the Three20 framework for the applications navigation. Three20 is a framework that was originally developed by Joe Hewitt for Facebook’s iPhone application. It offers a huge amount of features and is a great tool for any iPhone developer, but it does have some conventions that may take some getting use to for an Objective-C developer. The framework tends to do a lot of things for you, and I spent a lot of time in the source trying to see exactly what that was and how it could be modified to create the best Vodpod iPhone application. It was something I had never worked with, but I’m glad I did in the end. After getting the hang of it, it really streamlined a lot of things that can take much longer. For example, it offers a method of routing views, which is similar to Rails and many other web frameworks routing. It was quite a change from the traditional stack view of the iPhone’s views, but it ended up being invaluable in creating video and user pages on the fly. I would recommend it to anyone trying to make a complicated iPhone application tallhat is heavily reliant on API’s.
I also ended up using code from allseeing-i.com for some of the networking. This framework also proved to be invaluable in allowing for really easy networking and interfacing with the Vodpod API. I would, also, recommend it to anyone.
The Vodpod iPhone application would also not be possible without the tremendous Vodpod API that aphyr(Kyle) built. It has some really great documentation and is lightning fast. If you need a great video API, I would recommend it over almost every other video API I’ve worked with. It is extremely easy and friendly. I’d definitely give it a try.
Buidling an iPhone application is an interesting endeavor for a small start-up. You have to think about how much users will use it and how much it can help bring value to your company. In our case that remains to be seen, but we believe it will be useful and important. A mobile application allows users to access your service from wherever and whenever they feel they need to in the best format possible. This is an important aspect in keeping a user happy, which is the life-blood of a good start-up, and we hope this app can provide that functionality.
In the end, I think the Vodpod iPhone application turned out to be one of the best video applications in the Apple App Store. It is designed well, thanks to Tom Genoni, and is lightning fast. It allows you to watch many more videos than Youtube’s application and, even more importantly, let’s you watch the better videos more often. It is a great way to pass the time when you’re away from your computer, and it is definitely worth downloading. Go ahead and check it out.
