Posts Tagged ‘iPhone app dvelopment’
06
Jul

This blog post covers how one can maintain state in an iPhone application. Everyday interactions with the environment require us to save some form of information or data either for immediate use or maybe later.

Take for example:

  • Saving phone numbers on your mobile.
  • Backing up electronic data on a portable hard drive.
  • Performing the “Save Game” routine while playing a critical mission of your favorite console game.
  • Saving drafts of emails.
  • Saving code during development! (I too am saving this document to spare the agony of re-typing by an accidental application Quit.)

All these actions of saving, give the ability to record all information that is gathered.

Likewise, saving the state of an application is an essential, although not commonly used practice in iPhone Application Development.

In this post I intend to throw some light on aspects of  ’state saving’.

Need for saving the state:

Consider the following situations -

  • A user can quit the application at any point in time.
  • The application is quit by the iPhone OS on an external event such as a phone call.
  • The application quits on an internal event such as the launch of the native Web Directions app/ Google Maps app.

For an application with a large number of screens (by screens I mean ‘views’), navigating through many screens to view desired information and then having the application quit accidentally or unexpectedly can get annoying. Especially if the applications flow (sequence in which views load on user interaction) requires executing search queries, entering criteria or just navigating a dozen screens!

In such cases saving the state along with the required user data helps to restore the same view that the user was on before the application quit, upon application re-launch.

What data to save?:

In order to save the state, it is absolutely crucial to save all the necessary data to bring back the correct screen on application re-launch.

This section I suppose is self explanatory, hence i’ll resort to just listing the data one may need to save.

  • User information( username, password )
  • User preferences( settings within the application )
  • Application flow data( user-saved criteria, searches executed )

When to save data?:

The answer to this question could vary depending on the context of an application. Data could be saved at regular intervals during application flow or on specific screens or just before the application quits. In iPhone projects there exists a method that is called just before the application quits.


- (void)applicationWillTerminate:(UIApplication *)application{

}

Any logic, if you choose to save data just before the application quits should go in there.

Keep in mind the priority of data to be saved, you would not want to add more overhead than already exists.

How to save the data?:

Lets get started.

1. NSUserDefaults:

The NSUserDefaults object is simply a great way to save data. The best part being that no pre-requisite database knowledge is required to use it.

Saving Data -

Using the setObject & like methods, one can save different type of data as shown below.

forKey represents the key to associate with the value.


NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];

// to save a Float

[savedData setFloat:3.14159 forKey:@"valueOfPi"];

// to save an NSInteger

[savedData setInteger:18 forKey:@"userAge"];

// to save an NSString

[savedData setObject:@"JackSparrow" forKey:@"username"];

[savedData synchronize];

The synchronize method syncs the in-memory cache with the defaults database.

You could also setBool, setDouble, setUrl.

Retrieving Data -

Retrieving the saved data is even simpler & self-explanatory!


NSUserDefaults *savedData = [NSUserDefaults standardUserDefaults];

// getting an Float

float dearPi = [savedData floatForKey:@"valueOfPi"];

// getting an NSInteger

NSInteger theAge = [savedData integerForKey:@"userAge"];

// getting an NSString

NSString *theUsername = [savedData stringForKey:@"username"];

2. .plist file:

The .plist (Property List) is a file containing a list of nested {key-value} pairs of data types such as strings, numbers, arrays & dictionaries. Plists are simple & effective, much like NSUserDefaults.

The Setup -

i.    Create a plist file in your application’s Xcode project, say savedData.plist.
ii.    Create a list of paths, we will use one of the paths to save the plist.

NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

iii.    From this list of paths, get a path to the documents directory.

NSString *documentsDir = [pathList objectAtIndex:0];

iv.    Now get a file path to the plist


NSString *plistPath = [documentsDirectory  stringByAppendingPathComponent:@"savedData.plist"];

Writing data to the plist -

[<SOME DATA> writeToFile:plistPath atomically:YES];

Reading data from the plist -

NSMutableArray *array = [[NSMutableArray alloc]initWithContentsOfFile:plistPath];

In addition to the above methods you could also experiment with using SQLite or CoreData.

How to save data using them requires a separate post and as such, is out of the scope of this article.

What Next?:

Now that we are done with saving all that we need, a little bit of common sense & planning will go a long way in restoring the application to its previous state on re-launch. Depending upon the heaviness of the screen the user needs to see on re-launch, one may execute any number of methods within the application code to perform the necessary processing. However, let the user know that the application hasn’t hung up and is just processing things before the last viewed screen is shown, using waiting/activity indicators and alerts with appropriate messages. Preferably, build a view that continues to show as long as the required view doesn’t show up. If for some reason, restoring state is not possible, don’t let the application stare blank at the user. Instead, load an appropriate view from where the user can continue. If all fails, take the user to the first view of the application with the indication that probably the data required to load the appropriate view is insufficient or the application was unable to restore the state.

A few pointers to consider:

  1. Do not try saving excessive amounts of data, it results in latency while the application is running.
  2. Whatever you save, make sure its complete.
  3. When you are retrieving what you have saved, make sure the data exists. Null or no values spell doom.
  4. Let the user know the application hasn’t given up on him/her. Indicate processing where required.
  5. Free what is not required. Memory is vital, use it wisely.

I hope this post benefits all those looking to understand the need of saving an application state.

Anup Dsouza
Anup Dsouza– Member of Mobile Center of Excellence