iPhone Development Tutorial – Create a Plist programmatically after user action

In this tutorial we are going to create a plist that holds and array. We will create this plist programmatically after a user has entered elements for an array and clicked a button. I’m going to go through the creation of the UI Interface pretty fast so we can get to the good stuff.

1.) Open Xcode and create a new Tab Bat Application named PlistTutorial2.

2.) Create a user interface that includes 5 UITextFields and a UIButton on the first view/tab. Mine looks like this.

FirstView

On the second tab/view, add a UITableView.

SecondView

3.) In the FirstViewController.h file create instance variables for our five UITextFields.

#import 

@interface FirstViewController : UIViewController 
{
	
	UITextField *textField1;
	UITextField *textField2;
	UITextField *textField3;
	UITextField *textField4;
	UITextField *textField5;
	
}

@property (nonatomic, retain) IBOutlet UITextField *textField1;
@property (nonatomic, retain) IBOutlet UITextField *textField2;
@property (nonatomic, retain) IBOutlet UITextField *textField3;
@property (nonatomic, retain) IBOutlet UITextField *textField4;
@property (nonatomic, retain) IBOutlet UITextField *textField5;

@end

Then synthesize those variables in the implementation file.

#import "FirstViewController.h"

@implementation FirstViewController

@synthesize textField1, textField2, textField3, textField4, textField5;

And add a method to dismiss the keyboard when a user hits the return key in the keyboard. Make sure you set the delegate for each text field as File’s Owner for this to work.

- (void)textFieldShouldReturn:(id)sender
{
	[sender resignFirstResponder];
}

Link all the instance variables up to the text fields in Interface Builder. You’ll have to set the class file to FirstViewController in the Identity Inspector.

4.) Create a SecondViewController to handle the UITableView in the second tab. Make sure you implement all the necessary table view methods.

#pragma mark -
#pragma mark Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{
    // Return the number of sections.
    return 1;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    // Return the number of rows in the section.
    return 5;
}


// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
	
    // Configure the cell...
	cell.textLabel.text = @"Array Element";
    
    return cell;
}

#pragma mark -
#pragma mark Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{
    // Navigation logic may go here. Create and push another view controller.
    /*
	 <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
	 [self.navigationController pushViewController:detailViewController animated:YES];
	 [detailViewController release];
	 */
}

At this point you might want to make sure your user interface is all working properly.

5.) Now we can move on to the code for adding the Plist. First we need to add an IBAction to our FirstViewController that will get called from our button in the view.

#import 

@interface FirstViewController : UIViewController 
{
	
	UITextField *textField1;
	UITextField *textField2;
	UITextField *textField3;
	UITextField *textField4;
	UITextField *textField5;
	
}

@property (nonatomic, retain) IBOutlet UITextField *textField1;
@property (nonatomic, retain) IBOutlet UITextField *textField2;
@property (nonatomic, retain) IBOutlet UITextField *textField3;
@property (nonatomic, retain) IBOutlet UITextField *textField4;
@property (nonatomic, retain) IBOutlet UITextField *textField5;

- (IBAction) saveArrayToPlist;


@end

6.) Next we need to implement this IBAction. It is in here that the Plist will get created. Make sure you go into Interface Builder and link the action to the button.

- (IBAction) saveArrayToPlist
{
	// First we create our array from the text retrieved from our UITextFields
	NSMutableArray *array = [[NSMutableArray alloc] init];
	[array addObject:textField1.text];
	[array addObject:textField2.text];
	[array addObject:textField3.text];
	[array addObject:textField4.text];
	[array addObject:textField5.text];
	
	// get paths from root direcory
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];
	
	// This writes the array to a plist file. If this file does not already exist, it creates a new one.
	[array writeToFile:plistPath atomically: TRUE];
	
}

That’s all there is to creating the new plist file.

7.) Now let’s access that plist file and populate our table view with it to see it in action. Open up SecondViewController.h and add a NSMutableArray. We are also going to add an IBOutlet for our UITableView and link it up in Interface Builder, this will allow us to reload the table data.

#import 

@interface SecondViewController : UIViewController 
{

	NSMutableArray	*array;
	
	UITableView		*tableView;
}

@property (nonatomic, retain) IBOutlet UITableView	*tableView;

@end

Open up the implementation file and in the viewWillAppear method we want to retrieve our plist file and populate our array from it.

- (void)viewWillAppear:(BOOL)animated
{
	// get paths from root direcory
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];
	
	array = [[NSMutableArray arrayWithContentsOfFile:plistPath] retain];
	
	[tableView reloadData];
	
}

Don’t forget to synthesize out tableView.

#import "SecondViewController.h"

@implementation SecondViewController

@synthesize tableView;

8.) Use our array to set the number of rows in the table view.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{
    // Return the number of rows in the section.
    return [array count];
}

9.) And finally set the textLabel.text in each row with the value in the array.

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }
	

    
    // Configure the cell...
	
	cell.textLabel.text	= [array objectAtIndex:indexPath.row];
    
    return cell;
}

10.) In order to see any changes you make to the list right away you’ll need to reload the table view. We’ll do this in the viewWillAppear method.

- (void)viewWillAppear:(BOOL)animated
{
	[tableView reloadData];
}

11.) That’s all there is to it. Click Build and Run and test it out.

First View

Table View

As always. Here’s the code.



This entry was posted in Data and tagged , , , , , , , , , . Bookmark the permalink.

14 Responses to iPhone Development Tutorial – Create a Plist programmatically after user action

  1. naSh says:

    Wow! Great Tutorial, Exactly what I was looking for! I only got one question:
    How could I retain the values added in the text fields, so that I could add, and not update (or erase past values), the new values entered by the user. And then add a method to delete the rows that are no longer used by the user. Thanks in advance!

    • naSh says:

      BTW, I want to use the several UITextFields in the First View and put them in the same row on the table on the Second View, therefore, each new input from the user will be displayed in a new row. Thanks in advance.

  2. Ignacio says:

    Hi! I have the same question. What do you need to change in the code provided in order to create new rows each time the user adds information. Instead of adding the info on different rows, add the info inside the same row. New info, new row.

  3. Kent says:

    I’m answering both at one time and using an answer I just gave in another post.

    A plist can hold an array so you could keep adding to the array if you really wanted to. A plist is read all at once so it is a memory hit with too much data. To use an array you would need to read the contents of the array then add to the array and then save it again.

    My guess is you would be better looking for a different way to save your data if you are going to be adding to it regularly. Take a look at the Core Data tutorials.

    • naSh says:

      Thanks for your reply. In my case I want to still use a plist. I understand I can read the array that has been already been saved and overwrite it with the new information provided by the user, and with that information, add a new row in the tableview. The problem is, I have been struggling to find how to do that. Considering there are two UItexfields in the first controller, following your tutorial, to add two colors in one same row, I find that the plist created contains the following:

      Red
      Black

      Now, in your tutorial, when the user fills the uitextfields agains, the table erases the array an writes the new array. I do not want to erase that first array, instead, if the user uses the uitextfields to add two more colors, I want a new array to be created

      Red
      Black

      Blue
      Green

      And the Table would show
      “1st Row = Red, Black”
      “2nd Row = Blue Green”
      I already know how to handle the first array in the same row. I only need to indicate to the saveArrayToPlist Method that I want to create a new array in the plist, if there is already an array and in the cellForRowAtIndexPath tell it to create a new row with the new array.

      I know that with this the plist is going to grow with several arrays, but I want to give the user the possibility to delete rows, and therefore, delete the arrays in the plist. I could also limit the user to only create max 10 rows.

      I hope I was clear since I would appreciate your kind help
      Thanks again.

      • Kent says:

        Okay I’ve tried given my opinion that plist probably isn’t the way to go, but since you seem determined let’s see if we can figure this out :)

        Here’s some pseudo code of what I’m talking about.

        Assume user has already entered the first two colors (Red and Black).

        Now user enters two more colors(Blue and Green) and hits save button.

        colorsArray = new array;
        colorsArray = data from plist; // at this point colorsArray has Red and Black)
        //now add the new colors
        colorsArray addOjects (Blue and Green);
        // now colorArray has (Red and Black and Blue and Green)
        save colorsArray to plist;
        // the plist gets overwritten but it contains all the colors

        Does that make sense? Before you save the new colors you read the plist and get the colors, add them to an array and then add the new colors to the same array and save it. The plist gets overwritten everytime (which I don’t know if there’s anyway around) but it gets written with all the colors.

  4. ranjit says:

    Hi kent ,your tutorial was helpful,I want to know can we go on adding a data to a plist so that it will not overwrite and so that we can display all the data inside rows in table view..
    suppose,I have a text field where the user enters the name and click on “save” button,so then the name appears on a row ,i can say it will appear on r0w (zero),now again the user will go to the text field and add one more name,and clicks “save”,then that name along should appear on row(one) and hence forth,,so how can we do this using your code..

    please suggest me

    Regards
    Ranjit

  5. Thanks for taking the time to post this and for your very helpful blog. You saved me
    a lot of frustration tonight. You’re a good man ;)

    Thanks,

    Michael

  6. Guntarion says:

    Thank you for the tutorial. The way you create and retrieve property list is MUCH MORE efficient than the example provided by Apple. Awesome! :-)

Add Comment Register



Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>