Saturday, December 25, 2010

Customised UITableView for iphone.

This article is for creating custom UITableViewCell. We can have textfield, buttons inside our uitableview. We need just to customise  tableViewCell.
The example below will illustrate how to use tableview. Also it will show how to add and delete rows dynamically from the table.

1. Add a new Objective C class file (choose subclass of as "UITableViewCell") say CustomTableCell.
2. Add a new User interface class of type Empty XIB say say CustomTableCell.xib.
3.Open the say CustomTableCell.xib file in the interface builder. Open library and drag one "Table View Cell" to your CustomTableCell.xib. Now click on the "Table View Cell" and in the inspector window click on "Table view cell identity".
Change the class to "CustomTableCell".


4. Click on the File's owner icon. and in the inspector window click on "Object identity".
Change the class to "TableTestViewController" (your view controller in which this table cell will be used).


5. Double click on the CustomTableCell in the interface builder and add two textField to the table cell content view.
6. In your CustomTableCell.h
@interface CustomTableCell : UITableViewCell {
UITextField *firstColumn;
UITextField *secondColumn;
}

@property (nonatomic, retain) IBOutlet UITextField *firstColumn;
@property (nonatomic, retain) IBOutlet UITextField *secondColumn;

@end

7. In your CustomTableCell implementation class.

@synthesize firstColumn, secondColumn;

- (id) init {
self = [super init];
if (self != nil) {
// initializations go here.
firstColumn = [[UITextField alloc]init];
secondColumn = [[UITextField alloc]init];
}
return self;
}

8. Now open the CustomTableCell.xib and bind firstColumn and secondColumn to the UITextFields.
9. To add tableView in the viewcontroller :
Make your view controller as delegate for the table. Say your view controller is :TableTestViewController.
So in TableTestViewController.h includes these lines:

@interface TableTestViewController : UIViewController <UITableViewDelegate>{
CustomTableCell *tableCell;
UITableView *tableView;
}

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

Also import CustomTableCell. Bind this tableView to the table added to your view controller in the interface builder.

10. Bind the delegate and datasource of the table to the viewController using interface builder.


11. In your TestTableViewController implementation class (TestTableViewController.m) add the following line to the viewDidLoad method
[tableView setEditing:YES animated:YES];

12. Define TOTAL_NO_ROWS in the file. eg.,

int TOTAL_NO_OF_ROWS = 2;
Also add these methods to the class:

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"MyIdentifier";
CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"CustomTableCell" owner:self options:nil];
cell = tableCell;
self.tableCell = nil;
}
// Configure the cell with the relevant data and style...
if(indexPath.row == TOTAL_NO_OF_ROWS){
cell.firstColumn.text = @"Add New";
[cell.firstColumn setBorderStyle:UITextBorderStyleNone];
[cell.secondColumn setBorderStyle:UITextBorderStyleNone];
cell.firstColumn.enabled = FALSE;
cell.secondColumn.enabled = FALSE;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
return cell;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger rows = TOTAL_NO_OF_ROWS;
if (self.tableView.editing) {
rows ++;
}
TOTAL_NO_OF_ROWS = rows;
return rows+1;
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCellEditingStyle style = UITableViewCellEditingStyleNone;
//Last row will have the add new icon.
//All other row will have style for delete only.
if (indexPath.row < TOTAL_NO_OF_ROWS) {
style = UITableViewCellEditingStyleDelete;
}else {
style = UITableViewCellEditingStyleInsert;
}
return style;
}

//commit the edit style accordingly.
// in case of delete reduce the total no of rows.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleInsert) {
NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init];
NSIndexPath *newPath = [NSIndexPath indexPathForRow:TOTAL_NO_OF_ROWS inSection:0];
[insertIndexPaths addObject:newPath];
[self.tableView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop];
}else if (editingStyle == UITableViewCellEditingStyleDelete) {
TOTAL_NO_OF_ROWS = TOTAL_NO_OF_ROWS -2;
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
}


13. We are done. The ui should look like the below one:

Touching on the delete icon you can delete the row or you can add a new row by just touching on the add new icon.
Thanks





3 comments:

  1. Wow, that's the thing I need!
    I'll use your article soon.

    Thanks for sharing!

    Dr.Luiji

    ReplyDelete
  2. Hi,

    Trying to get this to work, but getting error.


    'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

    Thanks in advance for any ideas...

    ReplyDelete
    Replies
    1. You have to connect the CustomTableCell to tableCell in the CustomTableCell.xib

      Delete