Search Posts in my Blog

Monday 27 August 2012

NSUserDefaults Tutorial



In this tutorial I will demonstrate how to use the NSUserDefaults class in order to save and update application settings. In the process, we will build a demo app called “Contact” that will store a user-supplied image and contact information.

What is the NSUserDefaults Class?

With the NSUserDefaults class, you can save settings and properties related to application or user data. For example, you could save a profile image set by the user or a default color scheme for the application. The objects will be saved in what is known as the iOS “defaults system”. The iOS defaults system is available throughout all of the code in your app, and any data saved to the defaults system will persist through application sessions. This means that even if the user closes your application or reboots their phone, the saved data will still be available the next time they open the app!
With NSUserDefaults you can save objects from the following class types:
  • NSData
  • NSString
  • NSNumber
  • NSDate
  • NSArray
  • NSDictionary
If you want to store any other type of object, such as a UIImage, you will typically need to archive it or wrap it in an instance of NSData, NSNumber, or NSString.
Now that you know a bit about what can be done with NSUserDefaults, let’s jump into learning how to use the defaults system with a simple sample app that will store contact information.

Step 1: Creating the Project

Open Xcode and select “Create a new Xcode project”. Select a View-based Application and click Next. Enter a name for your project (I’ve called mine “Contact”). Enter your Company Identifier and make sure you select iPhone for Device Family, because we are going to make an iPhone app. If you are done, click next. Choose a place to save your project and then click create.
NSUserDefaults Figure 1

Step 2: Designing the Interface

In the “Contact” folder in the “Project Navigator” click on ContactViewController.xib.
Drag three UITextFields from the library to the view and arrange them like below. Do the same with a UIImageView and two Round Rect Buttons.
Click The first TextField and type “First name” in the Placeholder text field. Now click the second TextField and type “Last name” in the Placeholder text field. At last, click the third and last TextField and type “age” in the Placeholder text field. For keyboard type, select Number Pad, because you will only need numbers to enter your age.
Change the text of the first button to “Save” and the text of the second button to “Choose Image”.
NSUserDefaults Figure 2
Now we are going the make the connections. Xcode 4 has an new easy and fast way to do so. Select the middle button of the Editor to show the “Assistant editor”.
NSUserDefaults Figure 3
Click the first name TextField and CTRL-drag to the interface. A pop-up will show, enter “firstNameTextField” for name and click “connect.”
NSUserDefaults Figure 3
Do the same with the Last name and age Text Field and the UIImageView, but call them lastNameTextField, ageTextField and contactImageView. For the buttons we need to change the connection to Action instead of Outlet. So CTRL-drag from the save button to the interface, but this time under the curly braces. Change the Connection to Action and enter “save” for name. Do the same with the Choose Image button, but this time enter “chooseImage” for name. Now the code of the ContactViewController.h should read as follows:
#import <UIKit/UIKit.h>

@interface ContactViewController : UIViewController {
    
    IBOutlet UIImageView *contactImageView;
    IBOutlet UITextField *firstNameTextField;
    IBOutlet UITextField *lastNameTextField;
    IBOutlet UITextField *ageTextField;
}

- (IBAction)save:(id)sender;
- (IBAction)chooseImage:(id)sender;

@end
Now we are done with the interface. Click Build and Run to see if it runs okay. Enter some text and close the app. If you open the app again, you will likely see that the text you entered is still there. If so, this is caused by the built-in multitasking capability of iOS. If you delete the app from the multitasking bar and open the app again, you will see that the text you entered is gone. In this tutorial we will use NSUserDefaults to save the information entered even if you “really” close the app. This will allow the data to persist through multiple sessions.

Step 3: Choosing an Image

Switch back to the standard Editor mode, so you have more space to work within. Open ContactViewController.h and add the UIImagePickerControllerDelegate and the UINavigationControllerDelegate.
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>
If you are done with that, open the ContactViewController.m and scroll down to the ChooseImage action and modify the code to read as follows:
- (IBAction)chooseImage:(id)sender 
{
    UIImagePickerController *picker = [[[UIImagePickerController alloc] init] autorelease];
    picker.delegate = self;
    picker.allowsEditing = YES;
    picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    [self presentModalViewController:picker animated:YES];
}
First, we create a UIImagePickerController, then we set the delegate to self. Next, we enable user editing, then set the source type to the photo library, and finally we show it with an animation to the user.
Under choose image action, ad the following image picker delegate methods:
#pragma mark - Image Picker Delegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo
{
    contactImageView.image = image;

 [picker dismissModalViewControllerAnimated:YES];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{

 [picker dismissModalViewControllerAnimated:YES];
}
In the first method, we set the contactImageView image to the selected image and then dismiss the UIImagePickerController. In the second method, we only dismiss the UIImagePickerController.

Step 4: Saving the Data

You can save text with the function: setObject:(id) forKey:(NSString *). The key needs to be a specific key for the object you save because you also need that key to get the saved data. You can save integers with the function: setInteger:(NSInteger) forKey:(NSString *). To save the image we first need to create an instance of NSData from it.
Go to the save action and modify the code to read as follows:
- (IBAction)save:(id)sender 
{
    // Hide the keyboard
    [firstNameTextField resignFirstResponder];
    [lastNameTextField resignFirstResponder];
    [ageTextField resignFirstResponder];
    
    // Create strings and integer to store the text info
    NSString *firstName = [firstNameTextField text];
    NSString *lastName  = [lastNameTextField text];
    int age = [[ageTextField text] integerValue];
    
    // Create instances of NSData
    UIImage *contactImage = contactImageView.image;
 NSData *imageData = UIImageJPEGRepresentation(contactImage, 100);

    
    // Store the data
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    [defaults setObject:firstName forKey:@"firstName"];
    [defaults setObject:lastName forKey:@"lastname"];
    [defaults setInteger:age forKey:@"age"];
    [defaults setObject:imageData forKey:@"image"];
    
    [defaults synchronize];
    
    NSLog(@"Data saved");
}
First we hide the keyboard. Then we create strings of the text you entered in the first and last name text field. We also create an integer of the age you entered. Than we store the image from contactImageView as an NSData object, because we can’t save a UIImage directly with NSUserDefaults. Then we store the data, we call the standardUserDefaults function to save data in it. At last we synchronize the standardUserDefaults database.

Step 5: Get the Saved Data

At last we want to get the saved data. We do this in the viewDidLoad method, because that method is called when the application opens. Scroll down to the “viewDidLoad” method, uncomment it, and modify the code as follows:
- (void)viewDidLoad
{
    // Get the stored data before the view loads
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    
    NSString *firstName = [defaults objectForKey:@"firstName"];
    NSString *lastName = [defaults objectForKey:@"lastname"];
    
    int age = [defaults integerForKey:@"age"];
    NSString *ageString = [NSString stringWithFormat:@"%i",age];
    
    NSData *imageData = [defaults dataForKey:@"image"];
 UIImage *contactImage = [UIImage imageWithData:imageData];
    
    // Update the UI elements with the saved data
    firstNameTextField.text = firstName;
    lastNameTextField.text = lastName;
    ageTextField.text = ageString;
    contactImageView.image = contactImage;
    
    [super viewDidLoad];
}
First we call the standardUserDefaults function again, so we can get the saved data. We put the first and last name in an NSString. Although the age is an integer, we create a string to store it, because we can’t directly set the text of an TextField to an integer. We put the image in an NSData object and then we create a UIImage from the NSData object. Finally, we update the UI element with the saved data.
Now that the app is finished, build and run it again. Enter your data and select an image. Close the app from the multitasking bar and then open the app again. The data should still be there this time, and if so, our demo app works!
Thanks for reading this tutorial about NSUserDefaults! If you have questions or comments on this tutorial, leave them in the comments section below!