3

Utilizing the method of populating a UITableView from this answer, and setting the table to edit mode via:

tableView.editing = true;

And adding these methods:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{

}

I am seeing that a user can accidentally(or intentionally) double tab the ordering handle and insert an empty row. This will also kill the scrolling for the table view. Here is an image:

iosbug

Between "Logs" and "Settings" there is an empty row. I have looped through all rows on the table view via the answers found here, and the empty rows are skipped over as if they don't exist.

I was able to remove the empty rows via [tableView reload] each time a row is moved, which unfortunately results in a kind of jarring snap. However, I haven't been able to re-enabled the scrolling. I am trying to avoid having to make the user close and redisplay the view.

Any one run across this issue and find a suitable work around?

EDIT:

Row deletion is irrelevant - this happens as a result of moving rows around

This is Xcode 6.1 on ios 8/7 - have also seen this Xcode 5.x -> ios 7/8. We are targeting ipads, so not sure if this is an issue on iphone

Also, better description of how to reproduce:

  • double tap cell and hold on second tap for a second
  • drag cell up or down

Posted on Apple forums and submitted bug to Apple. Here was the example project I submitted to them (in which I was able to reproduce said issue):

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.tableData = [NSMutableArray arrayWithObjects:@"One",@"Two",@"Three",@"Four",@"Five",
                        @"One",@"Two",@"Three",@"Four",@"Five",
                        @"One",@"Two",@"Three",@"Four",@"Five",
                        @"One",@"Two",@"Three",@"Four",@"Five",
                        @"One",@"Two",@"Three",@"Four",@"Five",
                        @"One",@"Two",@"Three",@"Four",@"Five", nil];
    self.tableView.editing = true;
    [self.tableView setTableFooterView:[UIView new]];
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    self.tableView.rowHeight = 20.0;

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"ScrollingDisplayCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if( cell == nil )
    {
        cell = [[[UITableViewCellNoPadding alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];   // MEMCHK: Autorelease so no ownership implications

        cell.textLabel.font = [UIFont fontWithName:@"Courier New" size:17.0];
        cell.textLabel.frame = cell.contentView.bounds;
    }
    // Configure the cell...
    cell.textLabel.text = [self.tableData objectAtIndex:indexPath.row];

    return cell;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    NSString *stringToMove = self.tableData[sourceIndexPath.row];
    [self.tableData removeObjectAtIndex:sourceIndexPath.row];
    [self.tableData insertObject:stringToMove atIndex:destinationIndexPath.row];
}

And here is UITableViewCellNoPadding : UITableViewCell:

// https://stackoverflow.com/questions/3467288/center-align-text-in-uitableviewcell-problem
-(void)layoutSubviews
{
    [super layoutSubviews];
    self.textLabel.frame = CGRectMake(0, self.textLabel.frame.origin.y, self.frame.size.width, self.textLabel.frame.size.height);
}

NOTE: It was more difficult to reproduce here than in my own app

Community
  • 1
  • 1
daniel
  • 41
  • 6
  • For `tableView:moveRowAtIndexPath:toIndexPath:`, do you have an implementation that changes the data to reflect the moved rows? `UITableView` can get very confused or upset when it asks its delegate/data source to change its data but the data doesn't reflect those changes. – Fabian Jan 06 '15 at 15:37
  • Yes, I am updating the array with the new positions and am still seeing the same results – daniel Jan 06 '15 at 17:36

1 Answers1

0

Since you specified that users should not be able to delete rows, I added editingStyleForRowAtIndexPath to always return UITableViewCellEditingStyleNone. Without this implementation, UITableViewCellEditingStyleDelete is returned by default.

With the implementation posted below, everything seems to behave well, and I've checked that all edits commit successfully to the table model.

I hope this helps!

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.tableModel = [NSMutableArray new];
    for (int i = 0; i < 30; i++) {
        [self addTableObject];
    }

    _tableView.delegate = self;
    _tableView.dataSource = self;
    _tableView.editing = true;

}

- (void) addTableObject
{
    NSString *rowValue = [NSString stringWithFormat:@"%i", _tableModel.count+1];
    [_tableModel addObject:rowValue];
}

#pragma mark - Table view delegate methods

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
                                      reuseIdentifier:CellIdentifier];
    }

    cell.textLabel.text = [_tableModel objectAtIndex:indexPath.row];

    return cell;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _tableModel.count;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    //Make change in data model
    id selectedValue = [_tableModel objectAtIndex:sourceIndexPath.row];
    [_tableModel removeObjectAtIndex:sourceIndexPath.row];
    [_tableModel insertObject:selectedValue atIndex:destinationIndexPath.row];
}

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewCellEditingStyleNone;
}
Sheamus
  • 6,506
  • 3
  • 35
  • 61
  • When you say "possible to delete", are you referring to the using the delete button? If so, I have actually disabled them in my application. The picture posted was with a different UITableView to ensure it wasn't my code causing the issue. I do not have that method, but I will implement it and see if it makes a difference – daniel Jan 14 '15 at 21:43
  • I was talking about there being no deletion code in the answer you linked to. So, I added the calls for updating the model and the table in tableView:commitEditingStyle:forRowAtIndexPath:. Let me know how it goes! – Sheamus Jan 14 '15 at 21:57
  • Just to clarify - it is not possible for the user to delete any rows. The array is refreshed each time the view is entered. However, I will post results once I have a chance to test. – daniel Jan 15 '15 at 19:32
  • Okay, cool. I just added `editingStyleForRowAtIndexPath` to the answer to disable editing. – Sheamus Jan 15 '15 at 20:00
  • Ok, this is the same code I have and I am seeing the issue. I am assuming tableView:commitEditingStyle:forRowAtIndexPath: is irrelevant? This does not happen as a result of hitting "delete". It happens when just moving the rows. Were you able to reproduce the listed issue before suggesting a fix? – daniel Jan 19 '15 at 15:38
  • I see, I wasn't sure if it was because you were not updating the model, because I did see some strange behavior when implementation is missing. And no, I was not able to reproduce the problem you described on the iPad. – Sheamus Jan 19 '15 at 17:40