Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

StasKalishenko

macrumors newbie
Original poster
Dec 4, 2008
3
0
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):

Code:
- (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;
}
 

Attachments

  • Screen1.png
    Screen1.png
    426.7 KB · Views: 1,929
  • Screen2.png
    Screen2.png
    432.1 KB · Views: 2,159
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"?
 
A matter of timing for me

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:
Code:
- (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:
Code:
- (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
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.