iOS applications allows the users to move their configurable clutter into the Settings area which can be easily accessed using the Setting icon on the iPhone screen. In this article we are going to create our own custom settings area where users are allowed to change application configuration.

Why Settings?

An iPhone application that is simple, clean and organized does well in the app store. One way to remove all the complexity is to move all the configurations into iPhone settings. This will present the users with the bare bone functional app without the clutter of settings and configurations. Below you can see a screenshot of applications whose settings are available on an iPhone:



In this article we will be creating a custom section just like above to hold our app settings.

Creating Settings Bundle:     

The first task is to add a "Settings" bundle to your project. Right click on the project and then select "Add New Item". From the Resource option select "Settings" bundle and add it to your project. Now you are ready to start writing your custom preferences.

Open the Root.plist file by clicking on it. It will display in the property list view. Property list view provides an easy way to change the settings of the properties using a user interface. We will add three items to the Preference Items section in the "Root.plist" file. The items are shown below:



If you are not comfortable using the property list view you can always right click on the Root.plist file and then open as "Source Code". This will format the Root.plist file as XML as shown below:




    PreferenceSpecifiers
    
        
            Title
            Credentials
            Type
            PSGroupSpecifier
        

        
       
        
            Type
            PSTextFieldSpecifier
            Title
            User Name
            Key
            HNUserNamePrefKey
            DefaultValue
           
        
        
       

        
       
            Type
            PSTextFieldSpecifier
            Title
            Password
            Key
            HNPasswordPrefKey
            DefaultValue
           
            IsSecure
            true

            
           

        
        
   

    StringsTable
    Root





Let's go through each item so you have understanding of different elements. Each element is represented by key-value pairs. In the following implementation one of the key is "Title" and the value is "Credentials". Another key is Type and the value is "PSGroupSpecifier".   



            Title
            Credentials
            Type
            PSGroupSpecifier
        



The value of the "Title" key which is "Credentials" is displayed on the settings area. The "Type" key represents the type of the element that will be displayed which in this case is a PSGroupSpecifier. There are several other preferences specifiers which can be used to create TextFields, Sliders, Switch Buttons. In the implementation below we created a TextField specifier.


 
        
            Type
            PSTextFieldSpecifier
            Title
            User Name
            Key
            HNUserNamePrefKey
            DefaultValue
           
        
        
       



Run the application in the simulator and then click on the "Settings" icon.



After you click on your application name in the "Settings" you will see your custom preferences as shown in the screenshot below:



Pretty cool right! In the next section we are going to demonstrate how to access the settings values in our code.

Accessing Settings Values:

The values you have setup in the Settings can be accessed using the NSUserDefaults class. But before trying to access the values we should register the default values. This is performed in the static "initialize" method inside the application delegate file as shown below:


+(void) initialize
{
    // register defaults
    
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSString *pListPath = [path stringByAppendingPathComponent:@"Settings.bundle/Root.plist"];
    NSDictionary *pList = [NSDictionary dictionaryWithContentsOfFile:pListPath];
    
    NSMutableArray *prefsArray = [pList objectForKey:@"PreferenceSpecifiers"];
    NSMutableDictionary *regDictionary = [NSMutableDictionary dictionary];
    
    for(NSDictionary *dict in prefsArray)
    {
        NSString *key = [dict objectForKey:@"Key"];
        
        if(key)
        {
            id value = [dict objectForKey:@"DefaultValue"];
            [regDictionary setObject:value forKey:key];
        }
        
    }
    
    [[NSUserDefaults standardUserDefaults] registerDefaults:regDictionary];

}


The above code will register the defaults for all the keys in the Root.plist file. Now, you can access the settings values using the following implementation:


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    
    NSString *username = [ud stringForKey:@"HNUserNamePrefKey"];
    NSLog(@"%@",username);
    
    NSString *password = [ud stringForKey:@"HNPasswordPrefKey"];
    NSLog(@"%@",password);
    
    // Override point for customization after application launch.
     
    self.taskViewController = [[TaskViewController alloc] init];
    
    _viewController = [[BakerNotificationViewController alloc] init];
    
    self.window.rootViewController = _viewController;
    [self.window makeKeyAndVisible];
    return YES;
}



The above code will display the username on the console window.

Refreshing the Settings Out of Suspended State:

Suspended state is when the application is not being used by the user but still running in the background. When the user makes the changes to the "Settings" they are not available to the user unless the user closes the application and restart again. You can access the notification sent by the settings change event by subscribing to the notification inside the application:didFinishLaunchingWithOptions method as shown below:


 // register change notifications
    [[NSNotificationCenter defaultCenter] addObserverForName:NSUserDefaultsDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note)
     {
         // get the user name and password and authenticate the user
        
         NSLog(@"settings changed!");
     }
     ];


Now, when you change the settings your application will get a notification.

References:

1) iPhone Programming The Big Nerd Ranch Guide by Joe Conway & Aaron Hillegass

Conclusion:

In this article we learned how to move the app configuration to "Settings" area and making the app itself less cluttered.