iPhone App displaying result of data model Lesson 5A. This is a two part lesson looking at how to create a data model to sit behind the table created in lesson 4. In this part the data model will be created and simply populated by hard coding data. In the second part (5B) the data model will be populated by data from the web.


In our previous tutorial, lesson 4, we created a table where the table cells were numbered and could be deleted, but were renumbered once the cells were redrawn. In order to create some persistent data behind the table we need to create a data model. So lets go.

Creating the Data Model and Methods

Create a new Objective C class.
Select Classes within XCode and right click to Add a New File. Give the new class a suitable name such as DataModel.

Screen shot 2009-11-01 at 10.06.08

For the data we need to declare two string variables to represent the summary and detail data within an instance of the model. Remember to declare the variables using the Retain property so the memory is not automatically released and to synthesize the variables in your .m file, (Hint: this was covered in lesson 3).

@interface DataElements : NSObject
{
NSString* summaryString;
NSString* detailString;

}

@property(retain) NSString* summaryString;
@property(retain) NSString* detailString;

@end

We then need to create the model itself. For this tutorial we will use a MutableArray,(Mutable means changeable). so we will declare the model as follows

@interface DataModel : NSObject
{
NSMutableArray* theDataElementStore;
}
@property (retain) NSMutableArray* theDataElementStore;

Again remembering to synthesize the theDataElementstore variable in the .m file.

Now we need to create the methods that can be performed on the data model. Firstly we need to allocate some memory for the model and initialise it. This can be done as follows

– (id) init
{
self = [super init];
if (self != nil)
{
theDataElementStore = [[NSMutableArray alloc] initWithCapacity:40];
}
return self;
}
(N.B. pressing esc and selecting the init definition will give the outline for this method. The only additional coding added is to initialise the data elements of our model, setting the array to have a capacity of 40 elements).

We also need to ensure we release the memory for the elements once they are no longer required. So we need to create a dealloc method for our data model.

– (void) dealloc
{
[
theDataElementStore release];
[
super dealloc];
}

Again the definition for this is available with a placeholder for us to add the release of the dataElements.

Next we need to create the other methods that may be required. We need to be able to add elements and we will need to be able to access the summary and detail data. Also, we added the delete functionality to the UI in the previous tutorial, so we will need a method to delete an element.

Lets add an element first. This method does not need to return anything but it does need to take in the data for the summary and the associated detail. So the definition of the method in our DataModel.h needs to be something like

-(void) addElement:(NSString*)summary withDescription:(NSString*)description;

And the actual method needs to create an instance of the DataElements by creating a new variable to set up the summary and description.

-(
void) addElement:(NSString*)summary withDescription:(NSString*)description
{
DataElements* newEntry = [[DataElements alloc] init];
newEntry.
summaryString = summary;
newEntry.
detailString = description;
[
theDataElementStore addObject:newEntry];
}

The methods required to access the summary and detail are similar. We need to take in the position of the data required within theDataElementStore and return the string held there. By introducing another variable (retStr) we can return the data within the summary, (or detail), or return a set string if no data is available.

-(NSString*) getSummary:(int) position
{
NSString* retStr = @”No data”;

DataElements* thisElement = [theDataElementStore objectAtIndex:position];

if (thisElement != nil)
{
retStr = thisElement.
summaryString;
}
return retStr;
}

I will let you determine how to code the method for getDetail to allow it to access the detailString member variable. In both cases you need to declare the method within your header file.

-(NSString*) getSummary:(int) position;

The following diagram shows a logical view of how the data model is mapped into memory.

datamodel memory

So now we can add new data and access that data we need the ability to delete it. For this we don’t need to return any value, (the lack of any exception tells us it must have succeeded), we just take in the position of the dataElement to be deleted.

-(void) deleteElement: (int)position
{
[
theDataElementStore removeObjectAtIndex:position];
}

Finally, we utilised a variable, (
numberOfRows), in the previous tutorial to control how many rows we could have in the table. Now that we have created our model we need to utilise the size of theDataElementStore instead. So a final method is required.

-(int) numberOfElements
{
return [theDataElementStore count];
}

Remember to add the method definition into your model.h file.

Utilising the Data Model

Now our methods are defined and created we need to utilise them within the RootViewController in place of the code we created in Tutorial 4.

First let us initialise the model with some data that will allow us to identify the summary and detail elements. For this we can create a method that sets the first 20 elements. We need to declare an instance of our data model within our RootViewController.h file and define our initialisation method.

@interface RootViewController : UITableViewController
{
DataModel* model;
}

-(void)initDataModel;

@end

You should have noticed that we no longer declare our
numberOfRows variable as we will replace that with our numberOfElements count.

Within our RootViewController.m file we can add the following.

-(void)initDataModel
{
if (model == nil)
{
model = [[DataModel alloc] init];
}

for(int i = 0; i 20 ; i++)
{
NSString* summary = [[NSString alloc] initWithFormat:@”This is summary %i”,i];
NSString* detail = [[NSString alloc] initWithFormat:@”This is detail %i”,i];

[model addElement:summary withDescription:detail];

[summary release];
[detail
release];
}
}

To ensure this method runs we will call it as soon as the view is loaded.

– (void)viewDidLoad
{
[
super viewDidLoad];

// Call to initialise our data model elements
[
self initDataModel];

// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.title = @”Tutorial List”;
}


Now when we
// Customize the number of rows in the table view. We need to return the number of elements within our model instead of our previous numberOfRows. So we add the following:-

return [model numberOfElements];

Instead of setting the cell.textLabel.text equal to the section and cell number we can set it to our summary data.

// Configure the cell.
cell.
showsReorderControl = true;
cell.
textLabel.text = [model getSummary:indexPath.row];

The detail is then set where we set up our second view controller before we release the memory allocated for it.

[detailViewController.textView setText:[model getDetail:indexPath.row]];
[detailViewController
release];
}

To allow the elements to be deleted we can now delete the row from the data source.

// Override to support editing the table view.
– (
void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Delete the row from the data source.
[
model deleteElement:indexPath.row];
[
tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}

Finally, we need to release the memory we allocated for our model.

– (void)dealloc
{
[
model release]; //Release memory for our data model

[super dealloc];
}

When you build and run your changes you should find a difference, not only with the contents of the summary and detail views, but also with the way the cells are deleted.

Screen shot 2009-11-02 at 10.55.43

Summary cells listed in numerical order.

Screen shot 2009-11-02 at 10.55.52

Detail cell number matches summary cell number.

Screen shot 2009-11-02 at 10.56.18

Lets delete a summary cell, (This is summary 3), and see what happens.


Screen shot 2009-11-02 at 10.56.24

Screen shot 2009-11-02 at 10.57.03

Even when you scroll the view the cell is deleted, there is no duplicate cell numbering as we had in tutorial 4 and no renumbering occurs. The cell this time has been deleted at source.

Next tutorial

There was a lot to cover in this tutorial so I took the decision to split it into two parts. The second part, (due before the week is over), will look at using the web as the source for our data.