PDA

View Full Version : Adding new row in TableView using insertRowsAtIndexPaths




StasKalishenko
Dec 24, 2008, 10:58 AM
Hi, guys. I try to add new row dunamically using insertRowsAtIndexPaths. But I get a small bug: the next group of TableView left trail of caption. My major functions and 2 screenshots (before editing and after):

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
//[super setEditing:editing animated:animated];
//[self.navigationItem setHidesBackButton:editing animated:animated];
//[tableView reloadData];

[super setEditing:editing animated:animated];
[self.navigationItem setHidesBackButton:editing animated:animated];

// Calculate the index paths for all of the placeholder rows based on the number of items in each section.
NSArray *indexPaths = [NSArray arrayWithObjects:
[NSIndexPath indexPathForRow:0 inSection:1],
nil];
[tableView beginUpdates];
[tableView setEditing:editing animated:YES];
if (editing) {
// Show the placeholder rows
[tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
} else {
// Hide the placeholder rows.
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
//[tableView reloadData];
}

// Update the data model according to edit actions delete or insert.
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
/*NSDictionary *section = [data objectAtIndex:indexPath.section];
if (section) {
NSMutableArray *content = [section valueForKey:@"content"];
if (content && indexPath.row < [content count]) {
[content removeObjectAtIndex:indexPath.row];
}
}*/
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
//EditingViewController *controller = [MasterViewController editingViewController];
EditingViewController *controller = self.editingViewController;
controller.editedObject = client;
switch (indexPath.section) {
case 0: {
controller.textValue = @"";
controller.editedFieldKey = @"Name";
controller.dateEditing = NO;
} break;
case 1: {
controller.textValue = @"";
controller.editedFieldKey = @"Communication";
controller.dateEditing = NO;
} break;
case 2: {
controller.textValue = @"";
controller.editedFieldKey = @"Adress";
controller.dateEditing = NO;
} break;
case 3: {
controller.textValue = @"";
controller.editedFieldKey = @"Comments";
controller.dateEditing = NO;
} break;
}
self.selectedIndexPath = indexPath;
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
}

#pragma mark -
#pragma mark <UITableViewDelegate, UITableViewDataSource> Methods

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tv {
// 4 sections, one for each property
return 4;
}

- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
// Only one row for each section
NSInteger count = 1;
// If we're in editing mode, we add a placeholder row for creating new items.
if ((section == 1) && (self.editing)) count++;
return count;
}

- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DetailCell *cell = (DetailCell *)[tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
if (cell == nil) {
cell = [[[DetailCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"MyIdentifier"] autorelease];
cell.hidesAccessoryWhenEditing = NO;
}
NSString *sectionName;
switch (indexPath.section) {
case 0: sectionName = @"Name"; break;
case 1: sectionName = @"Communication"; break;
case 2: sectionName = @"Address"; break;
case 3: sectionName = @"Comments"; break;
}
if ((indexPath.section == 1) && (indexPath.row > 0)) {
cell.prompt.text = [NSString stringWithFormat:@"Add new %@", sectionName];
cell.promptMode = YES;
} else {
switch (indexPath.section) {
case 0: self.title = cell.name.text = client.name;
cell.promptMode = NO;
break;
case 1: cell.name.text = client.communication;
cell.promptMode = NO;
break;
case 2: cell.name.text = client.address;
cell.promptMode = NO;
break;
case 3: cell.name.text = client.comments;
cell.promptMode = NO;
break;
}
}
return cell;
}

- (NSString *)tableView:(UITableView *)tv titleForHeaderInSection:(NSInteger)section {
// Return the displayed title for the specified section.
switch (section) {
case 0: return @"Name";
case 1: return @"Communication";
case 2: return @"Address";
case 3: return @"Comments";
}
return @"";
}

// Called after selection. In editing mode, this will navigate to a new view controller.
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.editing) {
// Don't maintain the selection. We will navigate to a new view so there's no reason to keep the selection here.
[tableView deselectRowAtIndexPath:indexPath animated:NO];
// Go to edit view
//NSDictionary *section = [data objectAtIndex:indexPath.section];
BOOL section = TRUE;
if (section) {
//EditingViewController *controller = [MasterViewController editingViewController];
EditingViewController *controller = self.editingViewController;
controller.editedObject = client;
switch (indexPath.section) {
case 0: {
controller.textValue = client.name;
controller.editedFieldKey = @"Name";
controller.dateEditing = NO;
} break;
case 1: {
controller.textValue = client.communication;
controller.editedFieldKey = @"Communication";
controller.dateEditing = NO;
} break;
case 2: {
controller.textValue = client.address;
controller.editedFieldKey = @"Adress";
controller.dateEditing = NO;
} break;
case 3: {
controller.textValue = client.comments;
controller.editedFieldKey = @"Comments";
controller.dateEditing = NO;
} break;
}
self.selectedIndexPath = indexPath;
[self.navigationController pushViewController:controller animated:YES];
}
} else {
// This will give the user visual feedback that the cell was selected but fade out to indicate that no
// action is taken.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}

- (UITableViewCellAccessoryType)tableView:(UITableView *)tv accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath {
// Show the disclosure indicator if editing.
return (self.editing) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
}

// The editing style for a row is the kind of button displayed to the left of the cell when in editing mode.
- (UITableViewCellEditingStyle)tableView:(UITableView *)aTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
// No editing style if not editing or the index path is nil.
if (self.editing == NO || !indexPath) return UITableViewCellEditingStyleNone;
if (indexPath.row > 0) {
return UITableViewCellEditingStyleInsert;
} else {
return UITableViewCellEditingStyleDelete;
}
return UITableViewCellEditingStyleNone;
}



dejo
Dec 24, 2008, 11:48 AM
P.S.: Sorry for smiles in the code (I don't know how to remove them)
Haven't had a chance to look at your problem but I just wanted to suggest enclosing your code in the code/code tags (see the # in the toolbar) to avoid the smilies.

StasKalishenko
Dec 25, 2008, 01:39 AM
Haven't had a chance to look at your problem but I just wanted to suggest enclosing your code in the code/code tags (see the # in the toolbar) to avoid the smilies.

Thanks a lot.

But, did anybody face with the same problem. Where can I "dig"?

dejo
Dec 29, 2008, 11:37 AM
What do you mean by "left trail of caption"?

rragle
Feb 1, 2010, 11:35 AM
OK I ran into this problem too and for me it came to a matter of timing.

I had a function that was searching for bonjour machines and loading into section 1 of my tableView. Once they were all found, I was filling a local NSArray then calling [[self tableView] reloadSections:withRowAnimation where I shouldn't have been.

To fix MY redraw problem (which looked exactly like yours), instead of filling my array, then calling reloadSections, I changed my thinking and inserted new rows at that point via the insertRowsAtIndexPaths:withRowAnimation

Once I changed how the tableView was being manipulated, my other insert and deletion functions started working/drawing normally.

Here is an example of my before and after:
Before:

- (void) allServersFound {
// called when bonjourservices has listings of machines:
bonjourMachines = [bonjourService foundServers] // NSArray of server names;
[machineListings reloadSections:[[[NSIndexSet alloc] initWithIndex:1] autorelease] withRowAnimation:UITableViewRowAnimationNone];
}

After:

- (void) allServersFound {
// called when bonjourservices has listings of machines:
bonjourMachines = [bonjourService foundServers] // NSArray of server names;

// insert them
NSArray *newData = [NSArray arrayWithObjects:[NSIndexPath indexPathForRow:([bonjourMachines count] - 1) inSection:1], nil];
[[self tableView] insertRowsAtIndexPaths:newData withRowAnimation:UITableViewRowAnimationNone];
}


FYI Garbage collection not shown to keep code simple