Advertisement
iOS SDK

Updating iOS Applications with GroundControl

by

Submitting an update to the App Store is unavoidable if you want to add major enhancements to an application. However, it is cumbersome and time-consuming to go through the App Store review process for simple modifications. In this article, I will show you how to update an application remotely using the GroundControl project.


Introduction

The idea behind GroundControl is simple, the application fetches a remote property list and updates its NSUserDefaults with the contents of the property list. Even though many applications download data from a dedicated backend to dynamically update their contents, the strategy that I will lay out in this article is ideal if a dedicated backend isn't an option or exceeds your application's requirements.

The setup discussed in this tutorial is lightweight and inexpensive. Not only is it inexpensive, it is also easy to maintain, which is a factor often overlooked by both clients and developers.

It is important to emphasize that property lists are ideal for small chunks of data and shouldn't be used as a replacement for a dedicated backend. If an application needs to be updated on a daily basis with new content then the strategy dicussed in this tutorial won't cut it.

To illustrate how all the different pieces fit together, we will build an iOS application appropriately named Remote Control. Even though the application itself won't do much, by integrating GroundControl to update the application's NSUserDefaults it will become clear how easy it is to remotely update an application with very little overhead. Let's get started.


Step 1: Project Setup

Create a new project in Xcode by selecting the Single View Application template from the list of templates (figure 1). Name your application Remote Control, enter a company identifier, set iPhone for the device family, and check Use Automatic Reference Counting. Make sure to uncheck the remaining checkboxes for this project. Tell Xcode where you want to save your project and hit the Create button (figure 2).

Update Your Applications with Dropbox or GroundControl: Project Setup - Figure 1
Update Your Applications with Dropbox or GroundControl: Project Setup - Figure 2

Step 2: GroundControl

The name Mattt Thompson might sound familiar to you. He is one of the creators and the driving force behind AFNetworking, the most popular networking library for iOS and OS X. GroundControl is built on top of AFNetworking and provides an easy solution to remotely configure an application by updating the application's NSUserDefaults. It does this through a category on NSUserDefaults, which allows NSUserDefaults to update itself asynchronously with a remote property list.

It doesn't matter where the property list is located as long as it can be reached through the HTTP(S) protocol and the content type of the response is set to application/x-plist.

On the GitHub page of GroundControl, Mattt provides two examples of how to implement the server side of the story, one Ruby implementation and one Python implementation. However, I promised you that the setup would be lightweight and inexpensive. Instead of using a server that you need to maintain, we will be using Amazon's Simple Storage Service or S3. As I explained earlier, the requirements are simple, that is, (1) the file needs to be a property list and (2) the content type of the response needs to be application/x-plist. Amazon's S3 is a perfect fit.

Not only is AWS S3 perfectly suited for serving up static files, it has earned its stripes over the years. Even if your application reaches the top 10 in the App Store, S3 will keep serving up the property list this without problems. Before heading over to the AWS (Amazon Web Services) Console, your first need to integrate GroundControl into your project.


Step 3: Adding AFNetworking and GroundControl

GroundControl is built on top of AFNetworking, which means that you need to add AFNetworking to your Xcode project. Even though we could add AFNetworking and GroundControl using CocoaPods, we will add both libraries manually since some of you may not be familiar with CocoaPods. Download the latest version of AFNetworking and GroundControl and drag each library into your Xcode project. Make sure to copy the contents of the folder into your project by checking the checkbox labeled Copy items into destination group's folder (if needed) and don't forget to add both libraries to the Remote Control target (figures 3 and 4).

Update Your Applications with Dropbox or GroundControl: Adding AFNetworking and GroundControl - Figure 3
Update Your Applications with Dropbox or GroundControl: Adding AFNetworking and GroundControl - Figure 4

AFNetworking relies on the System Configuration and Mobile Core Services frameworks for some of its functionality. It is therefore necessary to link your project against those frameworks. Select your project in the Project Navigator and select the Remote Control target from the list of targets. Choose Build Phases at the top, open the Link Binary With Libraries drawer, and add both frameworks to your project (figure 5).

Update Your Applications with Dropbox or GroundControl: Adding the Necessary Frameworks - Figure 5

Before we can start working with AFNetworking and GroundControl, we need to update the project's Prefix.pch file by adding an import statement for the frameworks we just added to the project. Take a look at the snippet below for clarification.

//
// Prefix header for all source files of the 'Remote Control' target in the 'Remote Control' project
//

#import <Availability.h>

#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <MobileCoreServices/MobileCoreServices.h>
    #import <SystemConfiguration/SystemConfiguration.h>
#endif

Step 4: Integrating GroundControl

We start by adding two import statements to the application delegate's implementation file, one for AFNetworking and another for GroundControl. If you end up using AFNetworking in various places in your project then it might be a good idea to add the import statement for AFNetworking to your project's Prefix.pch file.

#import "AFNetworking.h"
#import "NSUserDefaults+GroundControl.h"

Integrating GroundControl is the easy part as it only requires two lines of code. In the application delegate's applicationDidBecomeActive: method, we call a helper method to initialize GroundControl.

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Initialize GroundControl
    [self initializeGroundControl];
}

The helper method couldn't be easier thanks to the category on NSUserDefaults provided by GroundControl. We create the URL for the property list and pass it as an argument in registerDefaultsWithURL:. This will ensure that the property list is downloaded asynchronously. Once downloaded, NSUserDefaults is automatically updated with the contents of the property list.

- (void)initializeGroundControl {
    NSURL *url = [NSURL URLWithString:@"https://www.example.com/RemoteControl.plist"];
    [[NSUserDefaults standardUserDefaults] registerDefaultsWithURL:url];
}

Another option is to call registerDefaultsWithURL:success:failure: instead if you prefer to work with success and failure callbacks. For even more control, GroundControl provides a third method, registerDefaultsWithURLRequest:success:failure:. This method accepts an instance of NSURLRequest as well as a success and failure block.

It might surprise you, but integrating GroundControl was the difficult part. The final two steps are (1) creating the property list and (2) uploading it to Amazon's S3.


Step 5: Create a Property List

Create a new file in Xcode by selecting the Resource tab on the left and choosing Property List on the right (figure 6). Name the file RemoteControl and save it to your computer's desktop. It is not necessary to add it to your Xcode project. The easiest way to edit the property list is in Xcode. Take a look at the screenshot below to see how the property list looks like and can be edited in Xcode (figure 7). Keep in mind that a property list can only contain booleans, dates, numbers, binary data, strings, arrays, and dictionaries. It is good practice to namespace the keys (for example, with the project's class prefix) to make sure they don't conflict with any other entries stored in NSUserDefaults.

Update Your Applications with Dropbox or GroundControl: Create a Property List - Figure 6
Update Your Applications with Dropbox or GroundControl: Create a Property List - Figure 7

Step 6: Upload the Property List

To use Amazon's Web Services, you need an Amazon account. The costs associated with Amazon's S3 are extremely low and chances are that you won't even be charged for quite some time since the property list is only a few kilobytes in size.

You can upload the property list to Amazon S3 using Amazon's AWS Console or by using an application that supports Amazon's S3, such as Panic's fantastic Transmit.

After uploading the property list, there are three things left to do, (1) copying the URL of the property list, (2) granting public access to the property list, and (3) setting the correct content type.

Copy the URL

In the AWS Console, select the property list and click the Properties button in the top right. Select the tab named Details in the properties panel (figure 8). Copy the link of the property list and update the initializeGroundControl method in the application delegate with the correct URL.

Update Your Applications with Dropbox or GroundControl: Copy the URL in the AWS Console - Figure 8

Grant Public Access

Select the tab named Permissions in the properties panel and add a new set of permissions to the property list by clicking the Add more permissions button. Set the grantee to Everyone and limit the permissions to Open/Download. This will make sure that your application can download the property list. Don't forget to click the save button to propagate the changes.

Update Your Applications with Dropbox or GroundControl: Granting Public Access to the Property List - Figure 9

Set Content Type

Select the tab named Metadata in the properties panel and set the value of the key Content-Type to application/x-plist. Don't forget to click the save button to propagate the changes.

Update Your Applications with Dropbox or GroundControl: Set the Content Type of the Response - Figure 10

Step 7: Build and Run

Your application is now ready to be updated remotely. How your application responds to the changes made by the property list depends on your application. This article only shows you how easy it is to remotely update an application without having to submit a new version to the App Store.

You can test if everything works by slightly modifying the initializeGroundControl method. Instead of invoking registerDefaultsWithURL:, we use registerDefaultsWithURL:success:failure: provided by GroundControl. If you have implemented GroundControl correctly, the dictionary of the success block should contain the data of the property list. Your application's NSUserDefaults will be updated automatically.

- (void)initializeGroundControl {
    NSURL *url = [NSURL URLWithString:@"https://s3.amazonaws.com/com.mobiletuts.bartjacobs/RemoteControl.plist"];
    [[NSUserDefaults standardUserDefaults] registerDefaultsWithURL:url success:^(NSDictionary *defaults) {
        NSLog(@"Defaults > %@", defaults);

    } failure:^(NSError *error) {
        NSLog(@"Error > %@ with user info %@.", error, [error userInfo]);
    }];
}

Dropbox

The immense success and fast adoption rate of Dropbox has resulted in the emergence of numerous clever and useful applications. For people not familiar with AWS and Xcode, it might be easier to work with Dropbox. Even though Dropbox is a great solution and provides the option to make a file publicly accessible by placing it in the public Dropbox folder, Dropbox cannot be used with the current version of GroundControl. The reason is that the content type of a property list served by Dropbox is automatically set to text/plain instead of the required application/x-plist. AFNetworking throws an error due to the fact that the required content type does not match application/x-plist.

However, it is possible to use Dropbox to remotely update an application. The caveat is that you will need to do some of the heavy lifting yourself, that is, asynchronously downloading the property list and updating the application's NSUserDefaults.

Despite the usefulness of the public Dropbox folder, its future is uncertain. It is also unclear if there is a bandwith limit imposed on files in the public Dropbox folder. In other words, if you wish to use Dropbox for remotely updating an iOS or OS X application, keep in mind that it might break at some point or that your Dropbox account might get suspended due to exceeding certain limitations.


Conclusion

It isn't always necesarry to build a custom backend for an iOS or OS X application if all you need to do is update a handful of settings from time to time. The strategies discussed in this article demonstrate how to remotely update an application with a simple property list.

Of course, there are several other possibilities to remotely update an application. For example, it is possible to use a service like Parse. However, I find that even Parse is "too much" if all you want to do is update a handful of settings.

Related Posts
  • Code
    iOS SDK
    Exploring the Multipeer Connectivity framework: Project Setup78mpi preview image
    As with every major release, iOS 7 includes many new APIs that developers can take advantage of in their applications. In this tutorial, we'll take a look at a brand new framework introduced in iOS 7, the Multipeer Connectivity framework. This framework adds support for discovering, connecting to, and communicating with nearby services, such as iOS devices. In this tutorial, I will show you how to create a simple, multi-player game using this new framework.Read More…
  • Code
    iOS SDK
    Working with NSURLSession: AFNetworking 2.032pzi preview image@2x
    In the previous installments of this series, we've taken a close look at the NSURLSession API introduced in iOS 7 and OS X Mavericks. Networking on iOS and OS X has become much simpler and more flexible thanks to the NSURLSession API. Does this mean that you should stop using AFNetworking for your networking needs? And what about AFNetworking 2.0, which was introduced a few months ago? In this final installment, I will tell you about AFNetworking 2.0 and how it compares to the NSURLSession API.Read More…
  • Code
    iOS SDK
    Working with NSURLSession: Part 4E548b preview image@2x
    In the previous tutorial, we started creating a simple podcast client to put what we've learned about NSURLSession into practice. So far, our podcast client can query the iTunes Search API, download a podcast feed, and display a list of episodes. In this tutorial, we zoom in on another interesting aspect of NSURLSession, out-of-process downloads. Let me show you how this works.Read More…
  • Code
    iOS SDK
    Working with NSURLSession: Part 3E548b preview image@2x
    In the previous tutorials, we explored the fundamentals of the NSURLSession API. There is one other feature of the NSURLSession API that we haven't look into yet, that is, out-of-process uploads and downloads. In the next two tutorials, I will show you how to create a very simple podcast client that enables background downloads.Read More…
  • Code
    iOS SDK
    iOS 7 SDK: Background Transfer ServiceIcon ios7 v3
    This tutorial will show you how to use the background transfer service, a Multitasking API provided by iOS 7. I'll teach you how to create an app that will download a file without the application in the foreground. Once the file fully downloads, a notification message will pop-up. Continue reading to create this service!Read More…
  • Code
    iOS SDK
    iOS Succinctly - Asset ManagementIos succinctly preview1
    Now that we have a basic understanding of iOS scene management, the next big topic to tackle is how to manage the multimedia assets in an application. iOS apps store their assets using the same hierarchical file system as any other modern operating system. Text, image, audio, and video files are organized into folders and accessed using familiar file paths like Documents/SomePicture.png.Read More…