The Backwards Compatibility Blues: supporting iOS 3.1 – 4.2
By Ross on March 15th, 2011 in TechnobabbleTags: Animal Phone, backwards compatibility, development, iOS
In the creation of our new app, Animal Phone, we wanted to make sure that users on older versions of iOS could use the app. Checking the analytics for our existing apps, we found that 3.1 is still reasonably popular, though falling fast. 3.0 is <1% so we decided to let < 3.1 go and make sure 3.1+ works for our app.
Along the way we found quite a few issues. Below are some of the problems we encountered and how to resolve them.
Crashing before we even start
Right off the bat we have a problem. The very first time I put our app on a 3.1.3 iPod Touch I get this error:
dyld: Symbol not found: __NSConcreteStackBlock Referenced from: /var/mobile/Applications/192B30ED-16AC-431E-B0E9-67C1F41FD5DA/MyApp.app/MyApp Expected in: /usr/lib/libSystem.B.dylib
Wait a minute, I’m not even using blocks! I know I can’t use blocks in 3.1 but the compiler does not. The problem is the new libSystem library contains references to blocks which causes a crash. The solution is to “weak link” the library in your Xcode build settings:
-weak_library /usr/lib/libSystem.B.dylib
Thanks to Brad on Stackoverflow for pointing me in the right direction:
http://stackoverflow.com/questions/3313786/ios-4-app-crashes-at-startup-on-ios-3-1-3-symbol-not-found-nsconcretestackblo
OK, one problem down.
Dealing with Multitasking Events
In 4.0 and up we got multitasking – wohoo! This means we need to respond to certain new events which were not possible before. In our Cocos2D scene we want to pause if the application enters the background, announced by the UIApplicationDidEnterBackgroundNotification notification. We also restart Cocos after the UIApplicationWillEnterForegroundNotification notification. Before multitasking, we didn’t have to worry about this because the app would simply terminate on close. If you use any openGL animation, it is critical that you pause it before entering the background to keep the device running smoothly.
The problem was these events, and their notifications, are unknown by 3.1, so we need to check the version before any calls of this type. We can check using the systemVersion property of the UIDevice:
if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 4.0)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_stopCocos) name:UIApplicationDidEnterBackgroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_restartCocos) name:UIApplicationWillEnterForegroundNotification object:nil];
}
This technique helped us out in a number of locations throughout the program.
Using New API Features
One of the nice things about working with the iOS API is Apple keeps giving us cool new features for *almost* free. In Animal Phone, we used the MPMoviePlayerController for video voicemails from the animals. In 3.2 and up, the movie player can play in line or fullscreen. Before 3.2 it was full screen only.
if ([moviePlayer respondsToSelector:@selector(setFullscreen:animated:)])
{
[[self.moviePlayer view] setFrame:[self.moviePlaybackView bounds]];
[self.moviePlaybackView addSubview:[self.moviePlayer view]];
}
Apple recommends testing for new features in the API using respondsToSelector, which we should all be familiar with from the multitude of Delegate pattern implementations in Cocoa. If you want to know more about the “Cocoa Way”, I highly recommend the excellent Cocoa Design Patterns (Kindle Edition
).
In this case
respondsToSelector:@selector(setFullscreen:animated:)
tells me that we are able to set the player up to fit our screen and we do so in the following lines. If setFullscreen is not available, the player will play full screen regardless.
Here is the result on 3.2 and up. 3.1.3 and lower simply play full screen.

There you have it, these three techniques solved the vast majority of the issues we faced. We are continuing to support 3.1 for the time being as our stats tell us it is still relevant, especially in a child focused app where children may have iPod Touches that parents don’t bother to keep up to date. It is enough of a challenge avoiding some awesome new features (like Blocks) and testing on old devices that I would recommend seriously considering dropping 3.x support in your projects unless there is a good reason to keep it.
Know any other good techniques? Let me know in the comments.





1 Trackback(s)