Update Reminders in 5-Minutes

Written by Bob Koon

Topics: How To

Here’s a super-simple way to gently remind your users that a new version of your app is available.

Ping A Server

All you need to do is put a php (or similar) file somewhere on your site that echos the current version. When your app launches, it retrieves the bundle version, pings the server to get the latest version and compares it. The sample code below displays an alert but you can do whatever you like of course.

Server-Side

The code on the server couldn’t be simpler (actually, it could; as a commenter pointed out, it could be a .txt file that just contains the version string). All it has to do is echo the current version (store this in a file called getversion.php):

<?php

echo "1.2.3";

?>


App-Side

The app is only slightly more involved as it has to be the one to do the work.

First, you need to ping the server and get the response (made simpler based on a commenter’s post):

NSString *  getLatestVersionFromServer(void)
{
    NSString *  server_response = nil;

    NSURL * web_addr    = [NSURL URLWithString: @"http://www.mysite.com/myappversion/getversion.php"];

    if (web_addr)
    {
        server_response = [NSString stringWithContentsOfURL:web_addr encoding:NSUTF8StringEncoding error:nil];
    }

    return(server_response);
}



Then wherever you want to do the check in your app (probably near the start), you can do it like so:

NSString *  app_version     = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
NSString *  server_version  = getLatestVersionFromServer();

if  (nil != server_version)
{
    if  (NSOrderedSame != [app_version compare:server_version])
    {
        UIAlertView *   alert;

        alert   = [[[UIAlertView alloc] initWithTitle: @"Update Available"
                    message: [NSString stringWithFormat: @"You are running an old version of MyApp (%@).\n\nThere is a newer version available (%@).\n\nPlease consider updating.",
                                app_version,
                                server_version]
                    delegate: self cancelButtonTitle: @"OK" otherButtonTitles: NULL] autorelease];

        [alert show];
    }
}


The Result

The code is Airplane Mode safe. The key for supporting that is the check to make sure the server version is not nil (it will be if the server can’t be pinged for whatever reason).

Here is what the above code looks like when it triggers (assuming the “Bundle version” entry in the info plist is set to 1.1.1):



So there you have it. A quick and easy way to gently remind your customers to stay current.

Enjoy!

9 Comments Comments For This Post I'd Love to Hear Yours!

  1. Dad says:

    nice, but why so much code and the ugly sprintf mess?

    Just make the NSURL with the string constant directly:

    NSURL * location    = [NSURL URLWithString: @"http://www.mysite.com/myappversion/getversion.php"];

    save you 7 lines of code (not counting blank lines), the memory of two copies of the string, and be clearer.

    • Bob Koon says:

      You’re exactly right. I did this post really quickly and took this code from another project that does more stuff there than what I’m showing here in this article. Basically overkill.

      For this specific example, your code is much clearer.

      Thanks!

    • Bob Koon says:

      Updated based on your comments. Thanks again for pointing that out.

  2. THETA Poker says:

    > The code on the server couldn’t be simpler. All it has to do is echo the current version (store this in a file called getversion.php):

    Actually, it can be a bit simpler. Just put the version number in a plain text file (e.g., version.txt)!

    Great stuff, otherwise. I’m doing something similar for a new app.

    • Bob Koon says:

      Yeah, that’s true. :)

      With using PHP, I’m setting it up for doing more complex tasks on the server side. For example, you can have different versions per language or per device. You can send that to the server and do a _GET to determine what the server should return.

      Thanks!

  3. Noel says:

    Good topic! However, stringWithContentsOfURL is a blocking call, isn’t it? If so you need to be running this from a separate thread. My preference when getting web pages is to use the asynchronous versions of the calls.

    • Bob Koon says:

      To be honest, I’m not sure if it’s blocking or not. I do know that it’s virtually instantaneous (in all the times I’ve ever used it; even in Airplane Mode) and usable from the main thread.

      • Yes, stringWithContentsOfURL is blocking. As Noel suggested, it would be better to do the version checking in a separate thread.

        In the case of being in airplane mode, the call fails immediately because there is no network available, however if you were in an area with poor wireless coverage, or your server was unreachable for some other reason, you could see an unacceptable delay in the app while waiting for the server communication to complete or timeout.

  4. bob says:

    if (NSOrderedSame != [app_version compare:server_version])
    should be written as
    if (![app_version isEqualToString:server_version])

Leave a Comment Here's Your Chance to Be Heard!