Search code examples
iosuiviewuitableviewtouches

Prevent UITableViewCell selection when dragging a subview


I have a UITableViewCell subclass and I have added a UIView to its contentView property. In order to enable dragging that subview, I have implemented the UIResponder appropriate methods:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  UITouch *touch = [touches anyObject];
  CGPoint currentLocation = [touch locationInView:self.superview];
  if (currentLocation.x >= self.rootFrame.origin.x) {
    return;
  }

  CGRect frame = self.frame;
  frame.origin.x = currentLocation.x;
  self.frame = frame;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  self.frame = self.rootFrame; // rootFrame is a copy of the initial frame
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
 [self touchesEnded:touches withEvent:event];
}

The subview can be dragged without problem, but the cell is being selected as well, so that -tableView:didSelectRowAtIndexPath: is being called.

How can I prevent that the cell becomes selected when the subview is being dragged?


Solution

  • To solve this situation I wrote a protocol for the subview:

    @protocol MyViewDelegate <NSObject>
    
    ///
    /// Tells the delegate that touches has begun in view
    ///
    - (void)view:(UIView *)view didBeginDragging:(UIEvent *)event;
    
    ///
    /// Tells the delegate that touches has finished in view
    ///
    - (void)view:(UIView *)view didFinishDragging:(UIEvent *)event;
    
    @end
    

    Then I completed the UIResponder methods in subview like this:

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      [self.delegate view:self didBeginDragging:event];
    }
    
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
      self.frame = self.rootFrame;
      [self.delegate view:self didFinishDragging:event];
    }
    

    Finally, I setup the cell as the delegate of the view and temporary cancel the cell selection while the dragging gestures are in progress:

    - (void)view:(UIView *)view didBeginDragging:(UIEvent *)event {
      [self setHighlighted:NO animated:NO];
      [self setSelectionStyle:UITableViewCellSelectionStyleNone];
    }
    
    - (void)vView:(UIView *)view didFinishDragging:(UIEvent *)event {
      [self setSelectionStyle:UITableViewCellSelectionStyleGray];
    }
    

    That's it