May 28, 2009

Never forget

Often when we are developing applications for the iPhone we want to enable extra 'tools' in the execution environment so we can get a better grasp of what our software is actually doing. Typically we'll use some kind of logging, and after reading Adhamh Findlay's post on the use of NSZombie I'll often have NSZombieEnabled turned on.

Both of these tools will have an impact on the behaviour of our application if enabled. Logging will certainly slow the application down and NSZombie can make the app run out of memory. Therefore, we need to be conscious of these potential hazards so that we don't try to start fixing problems that are actually just artifacts of the tools. More importantly we must be certain that none of these useful developer settings make their way into released code. It's not hard to imagine that one could let logging slip into a build - at a minimum this will cost you another cycle of building a release and potentially much, much much more.

We found ourselves making this mistake a couple of times with internal releases so thankfully it was only QA who complained and not customers. But having made this mistake we resolved to make it very difficult to repeat. So here's the first thing that our developers see when they start-up the application in a development mode:

Sure, dismissing the alert is a little annoying but it reminds us of the particulars of the current execution environment and saves us from making a costly mistake. We can then release our software with greater confidence. From a code perspective it's lightweight - in our viewDidLoad method of our root UIViewController we call:

    [ForgetfulDevelopersAlert showDeveloperWarningIfRequired];

In the ForgetfulDevelopersAlert implementation we check for logging like so:

    BOOL logging = NO;
    #if LOG_LEVEL != NONE
        logging = YES;

And we detect for NSZombie usage with:

    + (BOOL) __isNSZombieEnabled {
        return getenv("NSZombieEnabled")
            || getenv("NSAutoreleaseFreedObjectCheckEnabled");

With these flags available it is straight forward to construct a message and show the UIAlert:

    if (logging || zombies) {
        UIAlertView* alert = [[ForgetfulDevelopersAlert alloc]
            __initAlertWithLogging:logging andZombies:zombies];
        [alert show];
        [alert release];

This can of course be extend to check for other development settings. For example I know of one particular case where an app was submitted to the AppStore and it was not noticed until it had finally been approved that only 'test' ad banners had been enabled. Potentially this lost some revenue and required another approval cycle with Apple - but it is a very easy mistake to make that perhaps could have been avoided with something like:

    [ForgetfulDevelopersAlert showWarningIfTestAdsEnabled];


1 comment:

  1. Very simple solution that will certainly save us headaches down the road. Thanks again.