Tuesday, January 6, 2009

Creating a User Configurations on the iPhone

Reviewing some applications for the iPhone I noticed that some were making use of the Settings area to hold some User Configuration preference, which looked fantastic. I decided to investigate how this could be done in my own application and discovered that it is relatively east to create.

First within the XCode project we create a Settings.bundle file, by selecting File/New from the menu and selecting the Settings section on the left hand side of the dialogue.


This will create two new files in your project Root.strings and Root.plist. Open the Root.plist file by double clicking and you can see the editor dialogue appear with four default settings already entered under the 'PreferenceSpecifiers" section. You can modify or delete these as required.



There are a number of difference options open to the developer:
PSGroupSpecifier
This has only the one properties defined which is Title. This is used to group a number of related fields together.

PSTitleValueSpecifier
This displays a "Read Only" setting it cannot accept input from the user but can be used to display settings changed elsewhere.
Valid properties are: "Key", which is a string is used as a key to map to the value that a user will access the control. "DefaultValue" Another String property which stores the text that will be displayed in the specifier.

PSTextFieldSpecifier
Displays User enterable field. Properties include "Key" the name used to access the setting, "DefaultValue" a String property which is the initial value. "IsSecure" a boolean which defines if the charecters of the text field will be hidden, used for password fields. "KeyboardType" a String property which can have one of the following values: Alphabet, NumbersAndPunctuati on, NumberPad, URL, EmailAddress. This property specifies which type of keyboard to display when text field is selected. "AutocapitalizationType" a String property which can have one of the following values: None, Sentences, Words, AllCharacter. "AutoCorrectionType" string property which can have one of the following values: Default, No, Yes

PSSliderSpecifier
Displays a slider on a bar which allows the user to select a number in a specified range. "Key", a String property which holds the location of the control. "MinimumValue" and "MaximumValue" are numerical values which corresponds to the slider range. "DefaultValue" a numerical property which defines the first position of the slider.

PSToggleSwitchSpecifier
Displays a toggle switch which can be either On or Off. "Key", the name of the control. "TrueValue" and "FalseValue" defines the value of the control when it is in the On or Off position.". "DefaultValue", boolean property which defines the position of the Toggle button the first time it is loaded.

PSMultiValueSpecifier
Displays a list in a second view and allows the user to select one element from the list. "Key", defines the name of the key. "Values" of type Array which stores sub-elements of type String, each element provides a a possible value for the control to take. "DefaultValue" a String property that defines the initial value of the control, should be one of the elements of the Values list.

PSChildPaneSpecifier
Displays the contents of another Settings file which is useful if you want to break teh configuration up into various related sections. "Key", is the name of the control. "File" is the name of other plist file without the extension.


Testing the values in code
The simple way to read teh values in your application is to use the following
NSString *hostServicey_key = [[NSUserDefaults standardUserDefaults] stringForKey:@"hostService_key"];
Which should look through the settings field and retrieve the value of the property with the "Key" of "hostService_key".

I have however noticed that this value was being set to "nil" if the application was loaded onto the iPhone for the first time. The only way around this was to check the value before using it. If however the User goes into the Settings area first there is no problem.

// The URL of the Webserver
NSString *hostServicey_key = [[NSUserDefaults standardUserDefaults] stringForKey:@"hostService_key"];
//If the first value is nil, then we know that the defaults are not set.
if(hostServicey_key == nil)
{
//Get the bundle path
NSString *bPath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPath = [bPath stringByAppendingPathComponent:@"Settings.bundle"];
NSString *plistFile = [settingsPath stringByAppendingPathComponent:@"Root.plist"];

//Get the Preferences Array from the dictionary
NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile];
NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"];

//Loop through the array
NSDictionary *item;
for(item in preferencesArray)
{
//Get the key of the item.
NSString *keyValue = [item objectForKey:@"Key"];

//Get the default value specified in the plist file.
id defaultValue = [item objectForKey:@"DefaultValue"];

if([keyValue isEqualToString:@"hostService_key"])
hostServicey_key = defaultValue;
}
}