Web updates of content in iOS apps

One common use for mobile apps is to expose a company’s repertoire of content.

Perhaps your app will present cooking recipes, or First Aid information for folks that hurt themselves hiking far from cell tower coverage.

One challenge often faced in these types of apps is how to keep the content up to date. Of course you could simply ship an update to your app, but your customers may get annoying having to update your app every few weeks.

A better way is to have a means to update the content as it changes. The code I am presenting here is designed to do just that.

Introducing ContentBundle

The ContentBundle library aims to solve this problem by allowing you to embed content inside your application as a ZIP archive. When the application starts up the first time it will copy the contents of the ZIP file into your application’s Documents directory. All of the ZIP archive’s folders structure is pulled over intact, just as you would expect.

Once there you can use any of the built in file APIs to load content in, or even reference it inside of a WebView, which will be able to reference its HTML, CSS and images.

On subsequent startups the application will check its version against the already expanded content version, allowing updates of your application to deploy content updates.

But perhaps more than that, you can have the library reach out to your web site, determine if an update is available, and pull that update down.

To make this work we must first add a section into our application’s info.plist file:

Info.plist

This section is identifying that our content is in the test.zip file inside our app bundle. It’s version number is “1″. It will be expanded into our Documents folder in a sub-folder called “mytest”. Finally we have the URL where the library can obtain updates.

These settings, and the ZIP they references are what I refer to as a “content bundle”.

The library allow you to create multiple sections for different content bundles, which may be useful if some of your content will change more frequently than others.

To use the library in your code, first reference the library’s header file.

#import "SSContentBundle.h"

To reference content in a content bundle we might first access it.

The default bundle (which leverages the “SSContentBundle” key in our info.plist) is accessed via the mainBundle property.

SSContentBundle* provider = [SSContentBundle mainBundle];

You can obtain the full path of a file from the bundle thus:

NSString* path = [provider pathForFile:@"LiteUnzip.c"];
NSData* contents = [NSData dataWithContentsOfFile:path];

Web updates

At startup if you wish to check for content updates you can call the checkForUpdatesWithCompletionHandler: method.

[provider checkForUpdatesWithCompletionHandler:^(BOOL updateFound, NSError *error)
{
    if(error)
    {
        NSLog(@"Error removing old content: %@", [error localizedDescription]);
    }
}];

The block will be told if an update was found. If it was, the content ZIP file will have been downloaded, expanded and your old content replaced before the completion handler is called.

You may recall the content version URL was defined as:

http://www.stevesaxon.me/media/test/version.txt

This file contains the following:

3
test.zip

The first line is the server version number. Remember our info.plist said our client version was 1, so the server version is newer.

The second line is the relative URL to the server-based content update. In this case, “test.zip” is sitting in the same folder on the server as the version.txt file.

Under the covers

The TargetFolder key in the info.plist is used to identify the name of the target folder inside your application’s Documents directory.

It is also to identify the name of the version tracker file that is written by the library so that library knows the version of the content that is stored in the Documents directory. Initially the content of this file is written from the SourceVersion key in the info.plist, but it can be updated as part of a server content fetch.

The Documents directory may end up looking like this:

Example documents directory

Note the mytest-version.txt, which is the version tracker file. The mytest folder contains the contents of the ZIP file.

When a new content ZIP is downloaded, this folder is deleted and the updated content expanded in its place.

Getting involved

The library and sample code is available from github.

https://github.com/ssaxon/ContentBundle

If you this useful, leave a comment. Or jump over to github and get involved!

Leave a Reply

*