user286152
user286152

Reputation: 117

Dragging UITableView row to a different section results in crash

currently I have been trying to write a UITableView parent controller that monitors the current state of it's tableView. This tableView has 2 sections, and my plan is to have an NSMutableArray for each section that would mirror the current layout for saving to a NSUserDefaults page later. It is displayed in editing mode with flags that would allow the user to use Apple's default drag implementation

I have had constant crashes with cross-section dragging for unknown reasons with my current - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath I have no problem keeping my arrays organized while one row is moved within the same section, but I have not been able to solve this issue even when trying to manually refresh my rows . All the cell.reuseIdentifier's are supplied by me & unique so I am confident that there has not been any sort of compiler misinterpretation

Here is how the method looks

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
  if (sourceIndexPath != destinationIndexPath) { //not in the same spot
    //same section, different row only, works without issues
    if (sourceIndexPath.section == destinationIndexPath.section) {
          UITableViewCell * cell = [tableView cellForRowAtIndexPath:sourceIndexPath];
      if (destinationIndexPath.section == 0) {
        [self.visibleSections removeObject:cell.reuseIdentifier];
        [self.visibleSections insertObject:cell.reuseIdentifier atIndex:(int)destinationIndexPath.row];
      }
      else if (destinationIndexPath.section == 1) {
        [self.hiddenSections removeObject:cell.reuseIdentifier];
        [self.hiddenSections insertObject:cell.reuseIdentifier atIndex:(int)destinationIndexPath.row];
      }
    }

    //moving to different section
    else {
        NSString * id = [tableView cellForRowAtIndexPath:sourceIndexPath].reuseIdentifier;
        if (id.length != 0) {
             //movedf from visible to hidden
          if (sourceIndexPath.section == 0) {
            [self.visibleSections removeObject:id];
            [self.hiddenSections insertObject:id atIndex:(int)destinationIndexPath.row]; //CRASHING HERE
          }
          //moved from hidden to visible
          else {
            [self.hiddenSections removeObject:id];
            [self.visibleSections insertObject:id atIndex:(int)destinationIndexPath.row]; //CRASHING HERE
          }
       }
    }
}

From logging every line, I have determined the crash usually seems to be on the -(void)insertObject:atIndex: , in some cases I have tried puttng [tableView begin/endUpdates] around and it would work for one drag between sections but always crashing on a subsequent drag, but it also resulted in more than a few UI bugs with invisble rows which makes me think it isn't the route to go. I tried executed my array reordering asynchronously but that was an immediate crash as well

Ultimately I want to be able to get a representation of the current order of the tableView so I can save that to my NSUserDefaults for maintaining the user's desired order in future use, and would appreciate if anyone has a solution to this issue / a better way to keep track of the state. Thanks

Upvotes: 0

Views: 159

Answers (1)

Roy Falk
Roy Falk

Reputation: 1741

I'm not sure I understand the code and I'm missing the hiddenSections/visibleSections definition but I think you're missing something (and I apologize if I misunderstood).

  1. The reuse identifier should be identical to all similar cells. That's why it's called reuse. That way, when a cell moves out of view when scrolling, the object UITableViewCell can be reused and the text values plugged in without recreating it.
  2. You seem to be storing the value in the reuse value. That way, you can remove the value from one array and add it to another. However, (and this is the big guess), you don't seem to be storing it anywhere. I would expect you to do something like:

NSString *temp = [self.visibleSections removeObject:id]; [self.hiddenSections insertObject:temp atIndex:(int) destinationIndexPath.row];

  1. I think what happens is that within the same section, the UITableViewCell lives long enough for this to work. However, when moving to a different section, the garbage collection frees the cell in the step before.

Upvotes: 1

Related Questions